Skip to main content

TanStack Start Adapter

Adapter for integrating Better Auth Studio with TanStack Start applications.

Import

import { betterAuthStudio } from 'better-auth-studio/tanstack-start';

betterAuthStudio()

Creates a TanStack Start-compatible server route handler for Better Auth Studio.

Function Signature

function betterAuthStudio(
  config: StudioConfig
): ({ request }: TanStackStartHandlerContext) => Promise<Response>

Type Definitions

type TanStackStartHandlerContext = {
  request: Request;
};

Parameters

config
StudioConfig
required
Studio configuration object containing authentication and feature settings.

Returns

An async function that accepts a handler context with a Request and returns a Response

Usage

Server Route Handler

Create a catch-all server route:
// src/routes/api/studio/$.ts
import { createFileRoute } from '@tanstack/react-router';
import { betterAuthStudio } from 'better-auth-studio/tanstack-start';
import { auth } from '~/lib/auth';
import { defineStudioConfig } from 'better-auth-studio';

const studioConfig = defineStudioConfig({
  auth,
  basePath: '/api/studio',
  metadata: {
    title: 'My App Studio',
    theme: 'dark'
  },
  events: {
    enabled: true,
    tableName: 'auth_events'
  }
});

const handler = betterAuthStudio(studioConfig);

export const Route = createFileRoute('/api/studio/$')({
  server: {
    handlers: {
      GET: handler,
      POST: handler,
      PUT: handler,
      DELETE: handler,
      PATCH: handler,
    },
  },
});

Simplified Version

// src/routes/api/studio/$.ts
import { createFileRoute } from '@tanstack/react-router';
import { betterAuthStudio } from 'better-auth-studio/tanstack-start';
import { auth } from '~/lib/auth';

const handler = betterAuthStudio({ auth });

export const Route = createFileRoute('/api/studio/$')({
  server: {
    handlers: {
      GET: handler,
      POST: handler,
      PUT: handler,
      DELETE: handler,
      PATCH: handler,
    },
  },
});

With Access Control

// src/routes/api/studio/$.ts
import { createFileRoute } from '@tanstack/react-router';
import { betterAuthStudio } from 'better-auth-studio/tanstack-start';
import { auth } from '~/lib/auth';

const handler = betterAuthStudio({
  auth,
  access: {
    roles: ['admin'],
    allowEmails: ['[email protected]']
  }
});

export const Route = createFileRoute('/api/studio/$')({
  server: {
    handlers: {
      GET: handler,
      POST: handler,
      PUT: handler,
      DELETE: handler,
      PATCH: handler,
    },
  },
});

With Custom Middleware

// src/routes/api/studio/$.ts
import { createFileRoute } from '@tanstack/react-router';
import { betterAuthStudio } from 'better-auth-studio/tanstack-start';
import { auth } from '~/lib/auth';

const studioHandler = betterAuthStudio({ auth });

const withLogging = async ({ request }: { request: Request }) => {
  console.log(`Studio request: ${request.method} ${request.url}`);
  const response = await studioHandler({ request });
  console.log(`Studio response: ${response.status}`);
  return response;
};

export const Route = createFileRoute('/api/studio/$')({
  server: {
    handlers: {
      GET: withLogging,
      POST: withLogging,
      PUT: withLogging,
      DELETE: withLogging,
      PATCH: withLogging,
    },
  },
});

Implementation Details

Request Conversion

The adapter converts TanStack Start request objects to the universal format:
type UniversalRequest = {
  url: string;           // Pathname + search (with basePath stripped)
  method: string;        // request.method
  headers: Record<string, string>; // request.headers
  body?: any;            // Parsed from request
};

Base Path Handling

The adapter automatically strips the base path from URLs:
// If basePath is '/api/studio'
// And request URL is '/api/studio/users'
// The universal URL will be '/users'

Content Type Handling

The adapter handles multiple content types:
  • application/jsonrequest.json()
  • application/x-www-form-urlencoded → FormData converted to object
  • multipart/form-data → FormData converted to object
  • Other → Attempts to parse as text, then JSON

Error Handling

Errors are caught and returned as JSON responses:
{
  error: "Internal server error"
}
Status code: 500

TanStack Router Integration

File-based Routing

TanStack Start uses file-based routing with the $ parameter for catch-all routes:
src/routes/api/studio/$.ts → /api/studio/*

createFileRoute

The createFileRoute function creates type-safe route definitions:
export const Route = createFileRoute('/api/studio/$')({
  server: {
    handlers: {
      // HTTP method handlers
    },
  },
});

File Structure

src/
├── routes/
│   └── api/
│       └── studio/
│           └── $.ts
└── lib/
    └── auth.ts

Build docs developers (and LLMs) love