Skip to main content
Better Auth Studio provides adapters for multiple frameworks beyond Next.js and Express. This guide covers setup for Hono, SvelteKit, Remix, and Nuxt.

Hono

Hono is a fast, lightweight web framework for edge runtimes.

Installation

npm install better-auth-studio hono

Setup

1

Create Studio Config

studio.config.ts
import type { StudioConfig } from "better-auth-studio";
import { auth } from "./auth";

const config: StudioConfig = {
  auth,
  basePath: "/api/studio",
  access: {
    roles: ["admin"],
  },
};

export default config;
2

Add to Hono App

app.ts
import { Hono } from "hono";
import { betterAuthStudio } from "better-auth-studio/hono";
import studioConfig from "./studio.config";

const app = new Hono();

// Mount studio at /api/studio/*
app.all("/api/studio/*", betterAuthStudio(studioConfig));

// Your other routes
app.get("/", (c) => c.text("Hello Hono!"));

export default app;

Adapter Implementation

The Hono adapter converts Hono’s Context to a universal request format:
src/adapters/hono.ts
import type { Context } from "hono";
import { handleStudioRequest } from "../core/handler.js";
import type { StudioConfig, UniversalRequest } from "../types/handler.js";

export function betterAuthStudio(config: StudioConfig) {
  if (config.auth) {
    injectLastSeenAtHooks(config.auth, config);
    if (config.events?.enabled) injectEventHooks(config.auth, config.events);
  }

  return async (c: Context) => {
    try {
      const universalReq = await convertHonoToUniversal(c);
      const universalRes = await handleStudioRequest(universalReq, config);
      return sendHonoResponse(c, universalRes);
    } catch (error) {
      console.error("Studio handler error:", error);
      return c.json({ error: "Internal server error" }, 500);
    }
  };
}

SvelteKit

SvelteKit is a framework for building web applications with Svelte.

Installation

npm install better-auth-studio

Setup

1

Create Studio Config

studio.config.ts
import type { StudioConfig } from "better-auth-studio";
import { auth } from "./lib/auth";

const config: StudioConfig = {
  auth,
  basePath: "/api/studio",
  access: {
    roles: ["admin"],
  },
};

export default config;
2

Create Catch-All Route

Create a catch-all server route:
src/routes/api/studio/[...path]/+server.ts
import { betterAuthStudio } from "better-auth-studio/svelte-kit";
import studioConfig from "../../../../studio.config";

const handler = betterAuthStudio(studioConfig);

export async function GET(event) {
  return handler(event);
}

export async function POST(event) {
  return handler(event);
}

export async function PUT(event) {
  return handler(event);
}

export async function DELETE(event) {
  return handler(event);
}

export async function PATCH(event) {
  return handler(event);
}

Adapter Implementation

The SvelteKit adapter handles SvelteKit’s RequestEvent:
src/adapters/svelte-kit.ts
import type { RequestEvent } from "@sveltejs/kit";
import { handleStudioRequest } from "../core/handler.js";
import type { StudioConfig } from "../types/handler.js";

export function betterAuthStudio(config: StudioConfig) {
  if (config.auth) {
    injectLastSeenAtHooks(config.auth, config);
    if (config.events?.enabled) injectEventHooks(config.auth, config.events);
  }

  return async (event: RequestEvent): Promise<Response> => {
    try {
      const universalReq = await convertSvelteKitToUniversal(event, config);
      const universalRes = await handleStudioRequest(universalReq, config);
      return universalToResponse(universalRes);
    } catch (error) {
      console.error("Studio handler error:", error);
      return new Response(JSON.stringify({ error: "Internal server error" }), {
        status: 500,
        headers: { "Content-Type": "application/json" },
      });
    }
  };
}

Remix

Remix is a full-stack web framework focused on web standards.

Installation

npm install better-auth-studio

Setup

1

Create Studio Config

studio.config.ts
import type { StudioConfig } from "better-auth-studio";
import { auth } from "./lib/auth";

const config: StudioConfig = {
  auth,
  basePath: "/api/studio",
  access: {
    roles: ["admin"],
  },
};

export default config;
2

Create Resource Route

Create a splat route to handle all studio requests:
app/routes/api.studio.$.ts
import { betterAuthStudio } from "better-auth-studio/remix";
import studioConfig from "~/studio.config";
import type { LoaderFunctionArgs, ActionFunctionArgs } from "@remix-run/node";

const handler = betterAuthStudio(studioConfig);

export async function loader({ request }: LoaderFunctionArgs) {
  return handler({ request });
}

export async function action({ request }: ActionFunctionArgs) {
  return handler({ request });
}
The $ in the filename creates a catch-all route that matches /api/studio/*

Adapter Implementation

The Remix adapter works with Remix’s loader and action functions:
src/adapters/remix.ts
import { handleStudioRequest } from "../core/handler.js";
import type { StudioConfig } from "../types/handler.js";

export function betterAuthStudio(config: StudioConfig) {
  if (config.auth) {
    injectLastSeenAtHooks(config.auth, config);
    if (config.events?.enabled) injectEventHooks(config.auth, config.events);
  }

  return async ({ request }: { request: Request }): Promise<Response> => {
    try {
      const universalReq = await convertRemixToUniversal({ request }, config);
      const universalRes = await handleStudioRequest(universalReq, config);
      return universalToResponse(universalRes);
    } catch (error) {
      console.error("Studio handler error:", error);
      return new Response(JSON.stringify({ error: "Internal server error" }), {
        status: 500,
        headers: { "Content-Type": "application/json" },
      });
    }
  };
}

Nuxt

Nuxt is the intuitive Vue framework for building web applications.

Installation

npm install better-auth-studio

Setup

1

Create Studio Config

studio.config.ts
import type { StudioConfig } from "better-auth-studio";
import { auth } from "./lib/auth";

const config: StudioConfig = {
  auth,
  basePath: "/api/studio",
  access: {
    roles: ["admin"],
  },
};

export default config;
2

Create Server Route

Create a catch-all server API route:
server/api/studio/[...all].ts
import { betterAuthStudio } from "better-auth-studio/nuxt";
import studioConfig from "~/studio.config";

export default defineEventHandler(betterAuthStudio(studioConfig));
Nuxt automatically imports defineEventHandler and h3 utilities.

Adapter Implementation

The Nuxt adapter works with Nuxt’s h3 event handlers:
src/adapters/nuxt.ts
import { handleStudioRequest } from "../core/handler.js";
import type { StudioConfig } from "../types/handler.js";

export function betterAuthStudio(config: StudioConfig): (event: any) => Promise<Response | any> {
  if (config.auth) {
    injectLastSeenAtHooks(config.auth, config);
    if (config.events?.enabled) injectEventHooks(config.auth, config.events);
  }

  return async (event: any) => {
    try {
      const universalReq = await convertNuxtToUniversal(event, config);
      const universalRes = await handleStudioRequest(universalReq, config);
      return universalToResponse(universalRes);
    } catch (error: any) {
      // Handle client disconnection gracefully
      if (
        error?.code === "EPIPE" ||
        error?.code === "ECONNRESET" ||
        error?.message?.includes("aborted")
      ) {
        return new Response(null, { status: 499 });
      }

      console.error("Studio handler error:", error);
      return new Response(JSON.stringify({ error: "Internal server error" }), {
        status: 500,
        headers: { "Content-Type": "application/json" },
      });
    }
  };
}

Configuration Examples

With Access Control

All frameworks support the same configuration options:
studio.config.ts
import type { StudioConfig } from "better-auth-studio";
import { auth } from "./lib/auth";

const config: StudioConfig = {
  auth,
  basePath: "/api/studio",
  access: {
    roles: ["admin", "moderator"],
    allowEmails: ["[email protected]"],
  },
  metadata: {
    title: "Admin Dashboard",
    theme: "dark",
  },
};

export default config;

With Event Tracking

studio.config.ts
import type { StudioConfig } from "better-auth-studio";
import { auth } from "./lib/auth";

const config: StudioConfig = {
  auth,
  basePath: "/api/studio",
  events: {
    enabled: true,
    tableName: "auth_events",
    include: ["sign-in", "sign-up", "password-reset"],
  },
  lastSeenAt: {
    enabled: true,
  },
};

export default config;

Framework Comparison

FrameworkImport PathRoute TypeHandler Type
Next.jsbetter-auth-studio/nextjsCatch-all API route(request: Request) => Response
Expressbetter-auth-studio/expressExpress middlewareRouter
Honobetter-auth-studio/honoHono handler(c: Context) => Response
SvelteKitbetter-auth-studio/svelte-kitServer route(event: RequestEvent) => Response
Remixbetter-auth-studio/remixResource route({ request }) => Response
Nuxtbetter-auth-studio/nuxtServer API route(event) => Response

Troubleshooting

Import Errors

If you get import errors, ensure you’re using the correct adapter path:
// ✅ Correct
import { betterAuthStudio } from "better-auth-studio/hono";

// ❌ Wrong
import { betterAuthStudio } from "better-auth-studio";

TypeScript Errors

For framework-specific TypeScript errors, install the framework’s type definitions:
# SvelteKit
npm install --save-dev @sveltejs/kit

# Remix
npm install --save-dev @remix-run/node

# Nuxt
npm install --save-dev nuxt

Route Not Found

Ensure the catch-all route pattern is correct for your framework:
  • SvelteKit: [...path]/+server.ts
  • Remix: $.ts (splat route)
  • Nuxt: [...all].ts

Next Steps

Configuration

Learn about all configuration options

Next.js Setup

Set up with Next.js

Build docs developers (and LLMs) love