From 5870c81f1f3a502095fbaf4957f677d1a30c51ef Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 11:16:00 +0530 Subject: [PATCH 01/11] docs(guide): integrate better auth > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- .../framework/react/integrate-better-auth.md | 411 ++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 docs/start/framework/react/integrate-better-auth.md diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md new file mode 100644 index 0000000000..08d3a31b62 --- /dev/null +++ b/docs/start/framework/react/integrate-better-auth.md @@ -0,0 +1,411 @@ +--- +id: migrate-from-next-js +title: Migrate from Next.js +--- + +> [!IMPORTANT] +> This guide is based on the upcoming work in the `alpha` branch of **TanStack Start**. We are actively working on exciting new features, and this guide will be updated soon. + +This guide provides a step-by-step process to migrate a project from the Next.js App Router to **TanStack Start**. We respect the powerful features of Next.js and aim to make this transition as smooth as possible. + +## Step-by-Step (Basics) + +This step-by-step guide provides an overview of how to migrate your Next.js App Router project to TanStack Start using a starter template. The goal is to help you understand the basic steps involved in the migration process so you can adapt them to your specific project needs. + +### Prerequisites + +Before we begin, this guide assumes your project structure looks like this: + +``` +. +├── next.config.ts +├── package.json +├── postcss.config.mjs +├── tsconfig.json +├── README.md +├── public/ +│ ├── file.svg +│ ├── globe.svg +│ ├── next.svg +│ ├── vercel.svg +│ └── window.svg +└── src/ + └── app/ + ├── favicon.ico + ├── globals.css + ├── layout.tsx + └── page.tsx +``` + +Alternatively, you can follow along by cloning the following [starter template](https://github.com/nrjdalal/awesome-templates/tree/main/next.js-apps/next.js-start): + +```sh +npx gitpick nrjdalal/awesome-templates/tree/main/next.js-apps/next.js-start next.js-start-er +``` + +This structure or starter is a basic Next.js application using the App Router, which we will migrate to TanStack Start. + +### 1. Remove Next.js + +First, uninstall Next.js and remove related configuration files: + +```sh +npm uninstall @tailwindcss/postcss next +rm postcss.config.* next.config.* +``` + +### 2. Install Required Dependencies + +TanStack Start leverages [Vite](https://vite.dev) and TanStack Router: + +> [!NOTE] +> We're using the `alpha` version of TanStack Start and TanStack Router. This will change once they are merged into main. + +```sh +npm i @tanstack/react-router@alpha @tanstack/react-start@alpha vite +``` + +For Tailwind CSS and resolving imports using path aliases: + +```sh +npm i -D @tailwindcss/vite tailwindcss vite-tsconfig-paths +``` + +### 3. Update Project Configuration + +Now that you've installed the necessary dependencies, update your project configuration files to work with TanStack Start. + +- `package.json` + +```json +{ + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "start": "node .output/server/index.mjs" + } +} +``` + +- `vite.config.ts` + +```ts +// vite.config.ts +import tailwindcss from '@tailwindcss/vite' +import { tanstackStart } from '@tanstack/react-start/plugin/vite' +import { defineConfig } from 'vite' +import tsconfigPaths from 'vite-tsconfig-paths' + +export default defineConfig({ + server: { + port: 3000, + }, + plugins: [ + tailwindcss(), + // Enables Vite to resolve imports using path aliases. + tsconfigPaths(), + tanstackStart({ + tsr: { + // Specifies the directory TanStack Router uses for your routes. + routesDirectory: 'src/app', // Defaults to "src/routes" + }, + }), + ], +}) +``` + +By default, `routesDirectory` is set to `src/routes`. To maintain consistency with Next.js App Router conventions, you can set it to `src/app` instead. + +### 4. Adapt the Root Layout + +> TanStack Start uses a routing approach similar to Remix, with some changes to support nested structures and special features using tokens. Learn more about it at [Routing Concepts](/router/latest/docs/framework/react/routing/routing-concepts) guide. + +Instead of `layout.tsx`, create a file named `__root.tsx` in the `src/app` directory. This file will serve as the root layout for your application. + +- `src/app/layout.tsx` to `src/app/__root.tsx` + +```tsx +- import type { Metadata } from "next" // [!code --] +import { + Outlet, + createRootRoute, + HeadContent, + Scripts, +} from "@tanstack/react-router" +import "./globals.css" + +- export const metadata: Metadata = { // [!code --] +- title: "Create Next App", // [!code --] +- description: "Generated by create next app", // [!code --] +- } // [!code --] +export const Route = createRootRoute({ + head: () => ({ + meta: [ + { charSet: "utf-8" }, + { + name: "viewport", + content: "width=device-width, initial-scale=1", + }, + { title: "TanStack Start Starter" } + ], + }), + component: RootLayout, +}) + +- export default function RootLayout({ // [!code --] +- children, // [!code --] +- }: Readonly<{ // [!code --] +- children: React.ReactNode // [!code --] +- }>) { // [!code --] +- return ( // [!code --] +- // [!code --] +- {children} // [!code --] +- // [!code --] +- ) // [!code --] +- } // [!code --] +function RootLayout() { + return ( + + + + + + + + + + ) +} +``` + +> [!NOTE] +> When using `import "./globals.css"` directly, you may notice a flicker on the initial load. This is expected behavior during development and does not occur in production. It will be addressed in a future update. Alternatively, for now you can refer to this [example](https://tanstack.com/start/latest/docs/framework/react/examples/start-basic) for now to address this issue. + +### 5. Adapt the Home Page + +Instead of `page.tsx`, create an `index.tsx` file for the `/` route. + +- `src/app/page.tsx` to `src/app/index.tsx` + +```tsx +- export default function Home() { // [!code --] ++ export const Route = createFileRoute({ // [!code ++] ++ component: Home, // [!code ++] ++ }) // [!code ++] + ++ function Home() { // [!code ++] + return ( +
+ TanStack Logo +

+ Next.js TanStack Start +

+ + Docs + +
+ ) +} +``` + +### 6. Are we migrated yet? + +Before you can run the development server, you need to create a router file that will define the behavior of TanStack Router within TanStack Start. + +- `src/router.tsx` + +```tsx +import { createRouter as createTanStackRouter } from '@tanstack/react-router' +import { routeTree } from './routeTree.gen' + +export function createRouter() { + const router = createTanStackRouter({ + routeTree, + scrollRestoration: true, + }) + + return router +} + +declare module '@tanstack/react-router' { + interface Register { + router: ReturnType + } +} +``` + +> 🧠 Here you can configure everything from the default [preloading functionality](/router/latest/docs/framework/react/guide/preloading) to [caching staleness](/router/latest/docs/framework/react/guide/data-loading). + +Don't worry if you see some TypeScript errors at this point; the next step will resolve them. + +### 7. Verify the Migration + +Run the development server: + +```sh +npm run dev +``` + +Then, visit `http://localhost:3000`. You should see the TanStack Start welcome page with its logo and a documentation link. + +> If you encounter issues, review the steps above and ensure that file names and paths match exactly. For a reference implementation, see the [post-migration repository](https://github.com/nrjdalal/next-to-start). + +## Next Steps (Advanced) + +Now that you have migrated the basic structure of your Next.js application to TanStack Start, you can explore more advanced features and concepts. + +### Routing Concepts + +| Route Example | Next.js | TanStack Start | +| ------------------------------ | ---------------------------------- | ------------------------- | +| Root Layout | `src/app/layout.tsx` | `src/app/__root.tsx` | +| `/` (Home Page) | `src/app/page.tsx` | `src/app/index.tsx` | +| `/posts` (Static Route) | `src/app/posts/page.tsx` | `src/app/posts.tsx` | +| `/posts/[slug]` (Dynamic) | `src/app/posts/[slug]/page.tsx` | `src/app/posts/$slug.tsx` | +| `/posts/[...slug]` (Catch-All) | `src/app/posts/[...slug]/page.tsx` | `src/app/posts/$.tsx` | +| `/api/endpoint` (API Route) | `src/app/api/endpoint/route.ts` | `src/app/api/endpoint.ts` | + +Learn more about the [Routing Concepts](/router/latest/docs/framework/react/routing/routing-concepts). + +### Dynamic and Catch-All Routes + +Retrieving dynamic route parameters in TanStack Start is straightforward. + +```tsx +- export default async function Page({ // [!code --] +- params, // [!code --] +- }: { // [!code --] +- params: Promise<{ slug: string }> // [!code --] +- }) { // [!code --] ++ export const Route = createFileRoute({ // [!code ++] ++ component: Page, // [!code ++] ++ }) // [!code ++] + ++ function Page() { // [!code ++] +- const { slug } = await params // [!code --] ++ const { slug } = Route.useParams() // [!code ++] + return
My Post: {slug}
+} +``` + +> Note: If you've made a catch-all route (like `src/app/posts/$.tsx`), you can access the parameters via `const { _splat } = Route.useParams()`. + +Similarly, you can access `searchParams` using `const { page, filter, sort } = Route.useSearch()`. + +Learn more about the [Dynamic and Catch-All Routes](/router/latest/docs/framework/react/routing/routing-concepts#dynamic-route-segments). + +### Links + +```tsx +- import Link from "next/link" // [!code --] ++ import { Link } from "@tanstack/react-router" // [!code ++] + +function Component() { +- return Dashboard // [!code --] ++ return Dashboard // [!code ++] +} +``` + +Learn more about the [Links](../learn-the-basics.md#navigation). + +### Server ~Actions~ Functions + +```tsx +- 'use server' // [!code --] ++ import { createServerFn } from "@tanstack/react-start" // [!code ++] + +- export const create = async () => { // [!code --] ++ export const create = createServerFn().handler(async () => { // [!code ++] + return true +- } // [!code --] ++ }) // [!code ++] +``` + +Learn more about the [Server Functions](./server-functions.md). + +### Server Routes ~Handlers~ + +```ts +- export async function GET() { // [!code --] ++ export const ServerRoute = createServerFileRoute().methods({ // [!code ++] ++ GET: async () => { // [!code ++] + return Response.json("Hello, World!") + } ++ }) // [!code ++] +``` + +Learn more about the [Server Routes](./server-routes.md). + +### Fonts + +```tsx +- import { Inter } from "next/font/google" // [!code --] + +- const inter = Inter({ // [!code --] +- subsets: ["latin"], // [!code --] +- display: "swap", // [!code --] +- }) // [!code --] + +- export default function Page() { // [!code --] +- return

Font Sans

// [!code --] +- } // [!code --] +``` + +Instead of `next/font`, use Tailwind CSS’s CSS-first approach. Install fonts (for example, from [Fontsource](https://github.com/fontsource/fontsource)): + +```sh +npm i -D @fontsource-variable/dm-sans @fontsource-variable/jetbrains-mono +``` + +Add the following to `src/app/globals.css`: + +```css +@import 'tailwindcss'; + +@import '@fontsource-variable/dm-sans'; /* [!code ++] */ +@import '@fontsource-variable/jetbrains-mono'; /* [!code ++] */ + +@theme inline { + --font-sans: 'DM Sans Variable', sans-serif; /* [!code ++] */ + --font-mono: 'JetBrains Mono Variable', monospace; /* [!code ++] */ + /* ... */ +} + +/* ... */ +``` + +### Fetching Data + +```tsx +- export default async function Page() { // [!code --] ++ export const Route = createFileRoute({ // [!code ++] ++ component: Page, // [!code ++] ++ loader: async () => { // [!code ++] ++ const res = await fetch('https://api.vercel.app/blog') // [!code ++] ++ return res.json() // [!code ++] ++ }, // [!code ++] ++ }) // [!code ++] + ++ function Page() { // [!code ++] +- const data = await fetch('https://api.vercel.app/blog') // [!code --] +- const posts = await data.json() // [!code --] ++ const posts = Route.useLoaderData() // [!code ++] + + return ( +
    + {posts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` From 8480371202f040d2f93327936ec54d5616a93a93 Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 11:31:12 +0530 Subject: [PATCH 02/11] docs: tweaks > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- .../framework/react/integrate-better-auth.md | 680 ++++++++++-------- 1 file changed, 373 insertions(+), 307 deletions(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 08d3a31b62..45787ba710 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -1,212 +1,384 @@ --- -id: migrate-from-next-js -title: Migrate from Next.js +id: integrate-better-auth +title: Integrate Better Auth --- > [!IMPORTANT] > This guide is based on the upcoming work in the `alpha` branch of **TanStack Start**. We are actively working on exciting new features, and this guide will be updated soon. -This guide provides a step-by-step process to migrate a project from the Next.js App Router to **TanStack Start**. We respect the powerful features of Next.js and aim to make this transition as smooth as possible. +This guide provides a step-by-step process to integrate Better Auth with **TanStack Start**. We respect the powerful features of Better Auth and aim to make this implementation as smooth as possible. -## Step-by-Step (Basics) +## Step-by-Step -This step-by-step guide provides an overview of how to migrate your Next.js App Router project to TanStack Start using a starter template. The goal is to help you understand the basic steps involved in the migration process so you can adapt them to your specific project needs. +This step-by-step guide provides an overview of how to integrate Better Auth with TanStack Start using a starter template. The goal is to help you understand the basic steps involved in the implementation process so you can adapt them to your specific project needs. ### Prerequisites Before we begin, this guide assumes your project structure looks like this: -``` +```txt . -├── next.config.ts ├── package.json -├── postcss.config.mjs -├── tsconfig.json ├── README.md -├── public/ -│ ├── file.svg -│ ├── globe.svg -│ ├── next.svg -│ ├── vercel.svg -│ └── window.svg -└── src/ - └── app/ - ├── favicon.ico +├── tsconfig.json +├── vite.config.ts +└── src/ + ├── router.tsx + └── routes/ + ├── __root.tsx ├── globals.css - ├── layout.tsx - └── page.tsx + └── index.tsx ``` -Alternatively, you can follow along by cloning the following [starter template](https://github.com/nrjdalal/awesome-templates/tree/main/next.js-apps/next.js-start): +Alternatively, you can follow along by cloning the following [starter template](https://github.com/nrjdalal/awesome-templates/tree/main/tanstack-apps/tanstack-start): ```sh -npx gitpick nrjdalal/awesome-templates/tree/main/next.js-apps/next.js-start next.js-start-er +npx gitpick nrjdalal/awesome-templates/tree/main/tanstack-apps/tanstack-start better-start ``` -This structure or starter is a basic Next.js application using the App Router, which we will migrate to TanStack Start. +This structure or starter is a basic TanStack Start application, which we will integrate with TanStack Start. -### 1. Remove Next.js +![Image](https://github.com/user-attachments/assets/322f37b9-1af1-4082-bc88-56d270d684c5) -First, uninstall Next.js and remove related configuration files: +### 1. Install Required Dependencies ```sh -npm uninstall @tailwindcss/postcss next -rm postcss.config.* next.config.* +npm i better-auth drizzle-orm postgres +npm i -D drizzle-kit ``` -### 2. Install Required Dependencies +### 2. Configure Environment Variables -TanStack Start leverages [Vite](https://vite.dev) and TanStack Router: +```env +# .env -> [!NOTE] -> We're using the `alpha` version of TanStack Start and TanStack Router. This will change once they are merged into main. +BETTER_AUTH_URL=http://localhost:3000 +# can be generated using `npx nanoid` +BETTER_AUTH_SECRET= +# can be generated using `npx pglaunch` +POSTGRES_URL= -```sh -npm i @tanstack/react-router@alpha @tanstack/react-start@alpha vite +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= ``` -For Tailwind CSS and resolving imports using path aliases: +Updated project structure: -```sh -npm i -D @tailwindcss/vite tailwindcss vite-tsconfig-paths +```txt +. +├── .env // [!code ++] +├── package.json +├── README.md +├── tsconfig.json +├── vite.config.ts +└── src/ + ├── router.tsx + └── routes/ + ├── __root.tsx + ├── globals.css + └── index.tsx ``` -### 3. Update Project Configuration +### 3. Configure Drizzle ORM + +```ts +// drizzle.config.ts + +import { defineConfig } from "drizzle-kit" + +export default defineConfig({ + dialect: "postgresql", + dbCredentials: { + url: process.env.POSTGRES_URL!, + }, + schema: "src/db/schema", + out: "src/db/drizzle", +}) +``` + +```ts +// src/db/index.ts + +import { drizzle, type PostgresJsDatabase } from "drizzle-orm/postgres-js" +import postgres from "postgres" -Now that you've installed the necessary dependencies, update your project configuration files to work with TanStack Start. +declare global { + var db: PostgresJsDatabase +} -- `package.json` +let db: PostgresJsDatabase -```json -{ - "type": "module", - "scripts": { - "dev": "vite dev", - "build": "vite build", - "start": "node .output/server/index.mjs" +if (process.env.NODE_ENV === "production") { + db = drizzle({ + client: postgres(process.env.POSTGRES_URL!, { + ssl: { + rejectUnauthorized: true, + }, + }), + }) +} else { + if (!global.db) { + global.db = drizzle({ + client: postgres(process.env.POSTGRES_URL!), + }) } + db = global.db } -``` -- `vite.config.ts` +export { db } +``` ```ts -// vite.config.ts -import tailwindcss from '@tailwindcss/vite' -import { tanstackStart } from '@tanstack/react-start/plugin/vite' -import { defineConfig } from 'vite' -import tsconfigPaths from 'vite-tsconfig-paths' +// src/db/schema/auth.ts + +import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core" + +export const user = pgTable("user", { + id: text("id").primaryKey(), + name: text("name").notNull(), + email: text("email").notNull().unique(), + emailVerified: boolean("email_verified") + .$defaultFn(() => false) + .notNull(), + image: text("image"), + createdAt: timestamp("created_at") + .$defaultFn(() => /* @__PURE__ */ new Date()) + .notNull(), + updatedAt: timestamp("updated_at") + .$defaultFn(() => /* @__PURE__ */ new Date()) + .notNull(), +}) -export default defineConfig({ - server: { - port: 3000, +export const session = pgTable("session", { + id: text("id").primaryKey(), + expiresAt: timestamp("expires_at").notNull(), + token: text("token").notNull().unique(), + createdAt: timestamp("created_at").notNull(), + updatedAt: timestamp("updated_at").notNull(), + ipAddress: text("ip_address"), + userAgent: text("user_agent"), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), +}) + +export const account = pgTable("account", { + id: text("id").primaryKey(), + accountId: text("account_id").notNull(), + providerId: text("provider_id").notNull(), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + accessToken: text("access_token"), + refreshToken: text("refresh_token"), + idToken: text("id_token"), + accessTokenExpiresAt: timestamp("access_token_expires_at"), + refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), + scope: text("scope"), + password: text("password"), + createdAt: timestamp("created_at").notNull(), + updatedAt: timestamp("updated_at").notNull(), +}) + +export const verification = pgTable("verification", { + id: text("id").primaryKey(), + identifier: text("identifier").notNull(), + value: text("value").notNull(), + expiresAt: timestamp("expires_at").notNull(), + createdAt: timestamp("created_at").$defaultFn(() => /* @__PURE__ */ new Date()), + updatedAt: timestamp("updated_at").$defaultFn(() => /* @__PURE__ */ new Date()), +}) +``` + +Updated project structure: + +```txt +. +├── .env // [!code ++] +├── drizzle.config.ts // [!code ++] +├── package.json +├── README.md +├── tsconfig.json +├── vite.config.ts +└── src/ + ├── router.tsx + ├── db/ + │ ├── index.ts // [!code ++] + │ └── schema/ + │ └── auth.ts // [!code ++] + └── routes/ + ├── __root.tsx + ├── globals.css + └── index.tsx +``` + +### 4. Configure Better Auth + +```ts +// src/lib/auth/index.ts + +import { db } from "@/db" +import { account, session, user, verification } from "@/db/schema/auth" +import { betterAuth } from "better-auth" +import { drizzleAdapter } from "better-auth/adapters/drizzle" +import { reactStartCookies } from "better-auth/react-start" + +export const auth = betterAuth({ + database: drizzleAdapter(db, { + provider: "pg", + schema: { + user, + session, + account, + verification, + }, + }), + socialProviders: { + github: { + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET!, + }, }, - plugins: [ - tailwindcss(), - // Enables Vite to resolve imports using path aliases. - tsconfigPaths(), - tanstackStart({ - tsr: { - // Specifies the directory TanStack Router uses for your routes. - routesDirectory: 'src/app', // Defaults to "src/routes" - }, - }), - ], + plugins: [reactStartCookies()], }) ``` -By default, `routesDirectory` is set to `src/routes`. To maintain consistency with Next.js App Router conventions, you can set it to `src/app` instead. +```ts +// src/lib/auth/client.ts -### 4. Adapt the Root Layout +import { createAuthClient } from "better-auth/react" -> TanStack Start uses a routing approach similar to Remix, with some changes to support nested structures and special features using tokens. Learn more about it at [Routing Concepts](/router/latest/docs/framework/react/routing/routing-concepts) guide. +export const { signIn, signOut, useSession } = createAuthClient() +``` -Instead of `layout.tsx`, create a file named `__root.tsx` in the `src/app` directory. This file will serve as the root layout for your application. +```ts +// src/routes/api/auth/$.ts -- `src/app/layout.tsx` to `src/app/__root.tsx` +import { auth } from "@/lib/auth" -```tsx -- import type { Metadata } from "next" // [!code --] -import { - Outlet, - createRootRoute, - HeadContent, - Scripts, -} from "@tanstack/react-router" -import "./globals.css" - -- export const metadata: Metadata = { // [!code --] -- title: "Create Next App", // [!code --] -- description: "Generated by create next app", // [!code --] -- } // [!code --] -export const Route = createRootRoute({ - head: () => ({ - meta: [ - { charSet: "utf-8" }, - { - name: "viewport", - content: "width=device-width, initial-scale=1", - }, - { title: "TanStack Start Starter" } - ], - }), - component: RootLayout, +export const ServerRoute = createServerFileRoute().methods({ + GET: ({ request }) => { + return auth.handler(request) + }, + POST: ({ request }) => { + return auth.handler(request) + }, }) +``` -- export default function RootLayout({ // [!code --] -- children, // [!code --] -- }: Readonly<{ // [!code --] -- children: React.ReactNode // [!code --] -- }>) { // [!code --] -- return ( // [!code --] -- // [!code --] -- {children} // [!code --] -- // [!code --] -- ) // [!code --] -- } // [!code --] -function RootLayout() { - return ( - - - - - - - - - +```tsx +// src/components/auth-button.tsx + +import { signIn, signOut, useSession } from "@/lib/auth/client" +import { useLocation, useNavigate } from "@tanstack/react-router" + +export default function Component() { + const navigate = useNavigate() + const { pathname } = useLocation() + const { data: session } = useSession() + + if (session && pathname === "/") navigate({ to: "/dashboard" }) + if (!session && pathname === "/dashboard") navigate({ to: "/" }) + + return session ? ( + <> +

Welcome, {session.user.name}.

+ + + ) : ( + <> +

Please log in to continue.

+ + ) } ``` -> [!NOTE] -> When using `import "./globals.css"` directly, you may notice a flicker on the initial load. This is expected behavior during development and does not occur in production. It will be addressed in a future update. Alternatively, for now you can refer to this [example](https://tanstack.com/start/latest/docs/framework/react/examples/start-basic) for now to address this issue. +Updated project structure: -### 5. Adapt the Home Page +```txt +. +├── .env +├── drizzle.config.ts +├── package.json +├── README.md +├── tsconfig.json +├── vite.config.ts +└── src/ + ├── router.tsx + ├── db/ + │ ├── index.ts + │ └── schema/ + │ └── auth.ts + ├── lib/ + │ ├── auth/ + │ │ ├── client.ts // [!code ++] + │ │ └── index.ts // [!code ++] + └── routes/ + ├── api/ + │ └── auth/ + │ └── $.ts // [!code ++] + ├── components/ + │ └── auth-button.tsx // [!code ++] + ├── __root.tsx + ├── globals.css + └── index.tsx +``` -Instead of `page.tsx`, create an `index.tsx` file for the `/` route. +### 5. Generate Database Schema -- `src/app/page.tsx` to `src/app/index.tsx` +```sh +npx drizzle-kit push + +# [✓] Pulling schema from database... +# [✓] Changes applied +``` + +### 6. Add Auth Button Existing and New Routes ```tsx -- export default function Home() { // [!code --] -+ export const Route = createFileRoute({ // [!code ++] -+ component: Home, // [!code ++] -+ }) // [!code ++] +// src/routes/index.tsx + +import AuthButton from "@/components/auth-button" // [!code ++] + +export const Route = createFileRoute({ + component: Component, +}) -+ function Home() { // [!code ++] +function Component() { return ( -
+
TanStack Logo -

- Next.js TanStack Start +

+ TanStack +   + Start

+ // [!code ++] @@ -217,195 +389,89 @@ Instead of `page.tsx`, create an `index.tsx` file for the `/` route. } ``` -### 6. Are we migrated yet? - -Before you can run the development server, you need to create a router file that will define the behavior of TanStack Router within TanStack Start. +![Image](https://github.com/user-attachments/assets/776a43d6-cb24-403b-8923-d839386d576a) -- `src/router.tsx` +Just copy `src/routes/index.tsx` to `src/routes/dashboard.tsx`. ```tsx -import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routeTree } from './routeTree.gen' +// src/routes/dashboard.tsx -export function createRouter() { - const router = createTanStackRouter({ - routeTree, - scrollRestoration: true, - }) +import AuthButton from "@/components/auth-button" - return router -} - -declare module '@tanstack/react-router' { - interface Register { - router: ReturnType - } -} -``` - -> 🧠 Here you can configure everything from the default [preloading functionality](/router/latest/docs/framework/react/guide/preloading) to [caching staleness](/router/latest/docs/framework/react/guide/data-loading). - -Don't worry if you see some TypeScript errors at this point; the next step will resolve them. - -### 7. Verify the Migration - -Run the development server: - -```sh -npm run dev -``` - -Then, visit `http://localhost:3000`. You should see the TanStack Start welcome page with its logo and a documentation link. - -> If you encounter issues, review the steps above and ensure that file names and paths match exactly. For a reference implementation, see the [post-migration repository](https://github.com/nrjdalal/next-to-start). - -## Next Steps (Advanced) - -Now that you have migrated the basic structure of your Next.js application to TanStack Start, you can explore more advanced features and concepts. - -### Routing Concepts - -| Route Example | Next.js | TanStack Start | -| ------------------------------ | ---------------------------------- | ------------------------- | -| Root Layout | `src/app/layout.tsx` | `src/app/__root.tsx` | -| `/` (Home Page) | `src/app/page.tsx` | `src/app/index.tsx` | -| `/posts` (Static Route) | `src/app/posts/page.tsx` | `src/app/posts.tsx` | -| `/posts/[slug]` (Dynamic) | `src/app/posts/[slug]/page.tsx` | `src/app/posts/$slug.tsx` | -| `/posts/[...slug]` (Catch-All) | `src/app/posts/[...slug]/page.tsx` | `src/app/posts/$.tsx` | -| `/api/endpoint` (API Route) | `src/app/api/endpoint/route.ts` | `src/app/api/endpoint.ts` | - -Learn more about the [Routing Concepts](/router/latest/docs/framework/react/routing/routing-concepts). - -### Dynamic and Catch-All Routes - -Retrieving dynamic route parameters in TanStack Start is straightforward. - -```tsx -- export default async function Page({ // [!code --] -- params, // [!code --] -- }: { // [!code --] -- params: Promise<{ slug: string }> // [!code --] -- }) { // [!code --] -+ export const Route = createFileRoute({ // [!code ++] -+ component: Page, // [!code ++] -+ }) // [!code ++] - -+ function Page() { // [!code ++] -- const { slug } = await params // [!code --] -+ const { slug } = Route.useParams() // [!code ++] - return
My Post: {slug}
-} -``` - -> Note: If you've made a catch-all route (like `src/app/posts/$.tsx`), you can access the parameters via `const { _splat } = Route.useParams()`. - -Similarly, you can access `searchParams` using `const { page, filter, sort } = Route.useSearch()`. - -Learn more about the [Dynamic and Catch-All Routes](/router/latest/docs/framework/react/routing/routing-concepts#dynamic-route-segments). - -### Links - -```tsx -- import Link from "next/link" // [!code --] -+ import { Link } from "@tanstack/react-router" // [!code ++] +export const Route = createFileRoute({ + component: Component, +}) function Component() { -- return Dashboard // [!code --] -+ return Dashboard // [!code ++] + return ( +
+ TanStack Logo +

+ TanStack +   + Start +

+ +
+ Docs + +
+ ) } ``` -Learn more about the [Links](../learn-the-basics.md#navigation). - -### Server ~Actions~ Functions - -```tsx -- 'use server' // [!code --] -+ import { createServerFn } from "@tanstack/react-start" // [!code ++] - -- export const create = async () => { // [!code --] -+ export const create = createServerFn().handler(async () => { // [!code ++] - return true -- } // [!code --] -+ }) // [!code ++] -``` - -Learn more about the [Server Functions](./server-functions.md). +![Image](https://github.com/user-attachments/assets/7dc6acc1-9b65-4196-8c37-89a01d1eda84) -### Server Routes ~Handlers~ +Updated project structure: -```ts -- export async function GET() { // [!code --] -+ export const ServerRoute = createServerFileRoute().methods({ // [!code ++] -+ GET: async () => { // [!code ++] - return Response.json("Hello, World!") - } -+ }) // [!code ++] +```txt +. +├── .env +├── drizzle.config.ts +├── package.json +├── README.md +├── tsconfig.json +├── vite.config.ts +└── src/ + ├── router.tsx + ├── db/ + │ ├── index.ts + │ └── schema/ + │ └── auth.ts + ├── lib/ + │ ├── auth/ + │ │ ├── client.ts + │ │ └── index.ts + ├── components/ + │ └── auth-button.tsx + └── routes/ + ├── api/ + │ └── auth/ + │ └── $.ts + ├── __root.tsx + ├── globals.css + ├── index.tsx + └── dashboard.tsx // [!code ++] ``` -Learn more about the [Server Routes](./server-routes.md). - -### Fonts +### 7. Verify the Implementation -```tsx -- import { Inter } from "next/font/google" // [!code --] - -- const inter = Inter({ // [!code --] -- subsets: ["latin"], // [!code --] -- display: "swap", // [!code --] -- }) // [!code --] - -- export default function Page() { // [!code --] -- return

Font Sans

// [!code --] -- } // [!code --] -``` - -Instead of `next/font`, use Tailwind CSS’s CSS-first approach. Install fonts (for example, from [Fontsource](https://github.com/fontsource/fontsource)): +Run the development server: ```sh -npm i -D @fontsource-variable/dm-sans @fontsource-variable/jetbrains-mono -``` - -Add the following to `src/app/globals.css`: - -```css -@import 'tailwindcss'; - -@import '@fontsource-variable/dm-sans'; /* [!code ++] */ -@import '@fontsource-variable/jetbrains-mono'; /* [!code ++] */ - -@theme inline { - --font-sans: 'DM Sans Variable', sans-serif; /* [!code ++] */ - --font-mono: 'JetBrains Mono Variable', monospace; /* [!code ++] */ - /* ... */ -} - -/* ... */ +npm run dev ``` -### Fetching Data +Visit `http://localhost:3000` in your browser. You should see the TanStack Start splash page with a "Login with Github" button. Clicking this button will redirect you to the Github login page, and upon successful login, you will be redirected back to the dashboard. -```tsx -- export default async function Page() { // [!code --] -+ export const Route = createFileRoute({ // [!code ++] -+ component: Page, // [!code ++] -+ loader: async () => { // [!code ++] -+ const res = await fetch('https://api.vercel.app/blog') // [!code ++] -+ return res.json() // [!code ++] -+ }, // [!code ++] -+ }) // [!code ++] - -+ function Page() { // [!code ++] -- const data = await fetch('https://api.vercel.app/blog') // [!code --] -- const posts = await data.json() // [!code --] -+ const posts = Route.useLoaderData() // [!code ++] +You can also visit `http://localhost:3000/dashboard` directly, but you will be redirected to the home page if you are not logged in and vice versa. - return ( -
    - {posts.map((post) => ( -
  • {post.title}
  • - ))} -
- ) -} -``` +> If you encounter issues, review the steps above and ensure that file names and paths match exactly. For a reference implementation, see the [post-migration repository](https://github.com/nrjdalal/better-start) or website [demo](https://better-start.vercel.app). \ No newline at end of file From 9582afd888fb1564c89659018fbbd870fa5b1037 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 06:02:16 +0000 Subject: [PATCH 03/11] ci: apply automated fixes --- .../framework/react/integrate-better-auth.md | 136 +++++++++--------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 45787ba710..30156ee097 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -84,23 +84,23 @@ Updated project structure: ```ts // drizzle.config.ts -import { defineConfig } from "drizzle-kit" +import { defineConfig } from 'drizzle-kit' export default defineConfig({ - dialect: "postgresql", + dialect: 'postgresql', dbCredentials: { url: process.env.POSTGRES_URL!, }, - schema: "src/db/schema", - out: "src/db/drizzle", + schema: 'src/db/schema', + out: 'src/db/drizzle', }) ``` ```ts // src/db/index.ts -import { drizzle, type PostgresJsDatabase } from "drizzle-orm/postgres-js" -import postgres from "postgres" +import { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js' +import postgres from 'postgres' declare global { var db: PostgresJsDatabase @@ -108,7 +108,7 @@ declare global { let db: PostgresJsDatabase -if (process.env.NODE_ENV === "production") { +if (process.env.NODE_ENV === 'production') { db = drizzle({ client: postgres(process.env.POSTGRES_URL!, { ssl: { @@ -131,62 +131,66 @@ export { db } ```ts // src/db/schema/auth.ts -import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core" +import { boolean, pgTable, text, timestamp } from 'drizzle-orm/pg-core' -export const user = pgTable("user", { - id: text("id").primaryKey(), - name: text("name").notNull(), - email: text("email").notNull().unique(), - emailVerified: boolean("email_verified") +export const user = pgTable('user', { + id: text('id').primaryKey(), + name: text('name').notNull(), + email: text('email').notNull().unique(), + emailVerified: boolean('email_verified') .$defaultFn(() => false) .notNull(), - image: text("image"), - createdAt: timestamp("created_at") + image: text('image'), + createdAt: timestamp('created_at') .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), - updatedAt: timestamp("updated_at") + updatedAt: timestamp('updated_at') .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), }) -export const session = pgTable("session", { - id: text("id").primaryKey(), - expiresAt: timestamp("expires_at").notNull(), - token: text("token").notNull().unique(), - createdAt: timestamp("created_at").notNull(), - updatedAt: timestamp("updated_at").notNull(), - ipAddress: text("ip_address"), - userAgent: text("user_agent"), - userId: text("user_id") +export const session = pgTable('session', { + id: text('id').primaryKey(), + expiresAt: timestamp('expires_at').notNull(), + token: text('token').notNull().unique(), + createdAt: timestamp('created_at').notNull(), + updatedAt: timestamp('updated_at').notNull(), + ipAddress: text('ip_address'), + userAgent: text('user_agent'), + userId: text('user_id') .notNull() - .references(() => user.id, { onDelete: "cascade" }), + .references(() => user.id, { onDelete: 'cascade' }), }) -export const account = pgTable("account", { - id: text("id").primaryKey(), - accountId: text("account_id").notNull(), - providerId: text("provider_id").notNull(), - userId: text("user_id") +export const account = pgTable('account', { + id: text('id').primaryKey(), + accountId: text('account_id').notNull(), + providerId: text('provider_id').notNull(), + userId: text('user_id') .notNull() - .references(() => user.id, { onDelete: "cascade" }), - accessToken: text("access_token"), - refreshToken: text("refresh_token"), - idToken: text("id_token"), - accessTokenExpiresAt: timestamp("access_token_expires_at"), - refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), - scope: text("scope"), - password: text("password"), - createdAt: timestamp("created_at").notNull(), - updatedAt: timestamp("updated_at").notNull(), + .references(() => user.id, { onDelete: 'cascade' }), + accessToken: text('access_token'), + refreshToken: text('refresh_token'), + idToken: text('id_token'), + accessTokenExpiresAt: timestamp('access_token_expires_at'), + refreshTokenExpiresAt: timestamp('refresh_token_expires_at'), + scope: text('scope'), + password: text('password'), + createdAt: timestamp('created_at').notNull(), + updatedAt: timestamp('updated_at').notNull(), }) -export const verification = pgTable("verification", { - id: text("id").primaryKey(), - identifier: text("identifier").notNull(), - value: text("value").notNull(), - expiresAt: timestamp("expires_at").notNull(), - createdAt: timestamp("created_at").$defaultFn(() => /* @__PURE__ */ new Date()), - updatedAt: timestamp("updated_at").$defaultFn(() => /* @__PURE__ */ new Date()), +export const verification = pgTable('verification', { + id: text('id').primaryKey(), + identifier: text('identifier').notNull(), + value: text('value').notNull(), + expiresAt: timestamp('expires_at').notNull(), + createdAt: timestamp('created_at').$defaultFn( + () => /* @__PURE__ */ new Date(), + ), + updatedAt: timestamp('updated_at').$defaultFn( + () => /* @__PURE__ */ new Date(), + ), }) ``` @@ -217,15 +221,15 @@ Updated project structure: ```ts // src/lib/auth/index.ts -import { db } from "@/db" -import { account, session, user, verification } from "@/db/schema/auth" -import { betterAuth } from "better-auth" -import { drizzleAdapter } from "better-auth/adapters/drizzle" -import { reactStartCookies } from "better-auth/react-start" +import { db } from '@/db' +import { account, session, user, verification } from '@/db/schema/auth' +import { betterAuth } from 'better-auth' +import { drizzleAdapter } from 'better-auth/adapters/drizzle' +import { reactStartCookies } from 'better-auth/react-start' export const auth = betterAuth({ database: drizzleAdapter(db, { - provider: "pg", + provider: 'pg', schema: { user, session, @@ -246,7 +250,7 @@ export const auth = betterAuth({ ```ts // src/lib/auth/client.ts -import { createAuthClient } from "better-auth/react" +import { createAuthClient } from 'better-auth/react' export const { signIn, signOut, useSession } = createAuthClient() ``` @@ -254,7 +258,7 @@ export const { signIn, signOut, useSession } = createAuthClient() ```ts // src/routes/api/auth/$.ts -import { auth } from "@/lib/auth" +import { auth } from '@/lib/auth' export const ServerRoute = createServerFileRoute().methods({ GET: ({ request }) => { @@ -269,16 +273,16 @@ export const ServerRoute = createServerFileRoute().methods({ ```tsx // src/components/auth-button.tsx -import { signIn, signOut, useSession } from "@/lib/auth/client" -import { useLocation, useNavigate } from "@tanstack/react-router" +import { signIn, signOut, useSession } from '@/lib/auth/client' +import { useLocation, useNavigate } from '@tanstack/react-router' export default function Component() { const navigate = useNavigate() const { pathname } = useLocation() const { data: session } = useSession() - if (session && pathname === "/") navigate({ to: "/dashboard" }) - if (!session && pathname === "/dashboard") navigate({ to: "/" }) + if (session && pathname === '/') navigate({ to: '/dashboard' }) + if (!session && pathname === '/dashboard') navigate({ to: '/' }) return session ? ( <> @@ -287,7 +291,7 @@ export default function Component() { className="cursor-pointer rounded-full border px-4 py-1 text-gray-100 hover:opacity-80" onClick={async () => { await signOut() - navigate({ to: "/" }) + navigate({ to: '/' }) }} > Log Out @@ -300,8 +304,8 @@ export default function Component() { className="cursor-pointer rounded-full border px-4 py-1 text-gray-100 hover:opacity-80" onClick={async () => await signIn.social({ - provider: "github", - callbackURL: "/dashboard", + provider: 'github', + callbackURL: '/dashboard', }) } > @@ -357,7 +361,7 @@ npx drizzle-kit push ```tsx // src/routes/index.tsx -import AuthButton from "@/components/auth-button" // [!code ++] +import AuthButton from '@/components/auth-button' // [!code ++] export const Route = createFileRoute({ component: Component, @@ -396,7 +400,7 @@ Just copy `src/routes/index.tsx` to `src/routes/dashboard.tsx`. ```tsx // src/routes/dashboard.tsx -import AuthButton from "@/components/auth-button" +import AuthButton from '@/components/auth-button' export const Route = createFileRoute({ component: Component, @@ -474,4 +478,4 @@ Visit `http://localhost:3000` in your browser. You should see the TanStack Start You can also visit `http://localhost:3000/dashboard` directly, but you will be redirected to the home page if you are not logged in and vice versa. -> If you encounter issues, review the steps above and ensure that file names and paths match exactly. For a reference implementation, see the [post-migration repository](https://github.com/nrjdalal/better-start) or website [demo](https://better-start.vercel.app). \ No newline at end of file +> If you encounter issues, review the steps above and ensure that file names and paths match exactly. For a reference implementation, see the [post-migration repository](https://github.com/nrjdalal/better-start) or website [demo](https://better-start.vercel.app). From 55fbb7a3eb5f95bdb39d67acd59d6196b3f43b5c Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 11:53:27 +0530 Subject: [PATCH 04/11] docs: tweaks > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 30156ee097..1cceb82de7 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -49,7 +49,7 @@ npm i -D drizzle-kit ### 2. Configure Environment Variables -```env +```txt # .env BETTER_AUTH_URL=http://localhost:3000 From d63dfc70bca72394d605c7bc5e9791882343180b Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 12:00:24 +0530 Subject: [PATCH 05/11] docs: tweaks > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 1cceb82de7..4695ba74fb 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -6,7 +6,7 @@ title: Integrate Better Auth > [!IMPORTANT] > This guide is based on the upcoming work in the `alpha` branch of **TanStack Start**. We are actively working on exciting new features, and this guide will be updated soon. -This guide provides a step-by-step process to integrate Better Auth with **TanStack Start**. We respect the powerful features of Better Auth and aim to make this implementation as smooth as possible. +This guide provides a step-by-step process to integrate [Better Auth](https://better-auth.com) with **TanStack Start**. We respect the powerful features of Better Auth and aim to make this implementation as smooth as possible. ## Step-by-Step From 23d9ebcc3dc7babc8223c40c4b452a85e52c6e9e Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 12:05:19 +0530 Subject: [PATCH 06/11] chore: finalize > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 4695ba74fb..8d4dffe5e4 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -62,6 +62,8 @@ GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= ``` + + Updated project structure: ```txt From 3723804ee1ced491bb674abdef4610213af4a165 Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 12:11:54 +0530 Subject: [PATCH 07/11] chore: finalize > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 8d4dffe5e4..36ff16717e 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -200,7 +200,7 @@ Updated project structure: ```txt . -├── .env // [!code ++] +├── .env ├── drizzle.config.ts // [!code ++] ├── package.json ├── README.md From 526eee1999ab11ce9ef1405e2ce4a39ea97f71c2 Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 12:23:54 +0530 Subject: [PATCH 08/11] docs: tweaks > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 36ff16717e..b4baaae5c9 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -358,7 +358,7 @@ npx drizzle-kit push # [✓] Changes applied ``` -### 6. Add Auth Button Existing and New Routes +### 6. Add Auth Button to Existing and New Routes ```tsx // src/routes/index.tsx From 986759c66fc9c13df73dfb9732ac1a291ba795e2 Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 17:46:01 +0530 Subject: [PATCH 09/11] docs: tweaks > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index b4baaae5c9..b1cfa7620b 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -463,9 +463,9 @@ Updated project structure: │ └── auth/ │ └── $.ts ├── __root.tsx + ├── dashboard.tsx // [!code ++] ├── globals.css - ├── index.tsx - └── dashboard.tsx // [!code ++] + └── index.tsx ``` ### 7. Verify the Implementation From 2e4df21c266710c3a90699e0146e4585cb52faee Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 17:51:24 +0530 Subject: [PATCH 10/11] chore: fix trees > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- .../framework/react/integrate-better-auth.md | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index b1cfa7620b..4dcbddc076 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -22,7 +22,7 @@ Before we begin, this guide assumes your project structure looks like this: ├── README.md ├── tsconfig.json ├── vite.config.ts -└── src/ +└── src/ ├── router.tsx └── routes/ ├── __root.tsx @@ -73,7 +73,7 @@ Updated project structure: ├── README.md ├── tsconfig.json ├── vite.config.ts -└── src/ +└── src/ ├── router.tsx └── routes/ ├── __root.tsx @@ -206,7 +206,7 @@ Updated project structure: ├── README.md ├── tsconfig.json ├── vite.config.ts -└── src/ +└── src/ ├── router.tsx ├── db/ │ ├── index.ts // [!code ++] @@ -328,25 +328,25 @@ Updated project structure: ├── README.md ├── tsconfig.json ├── vite.config.ts -└── src/ +└── src/ ├── router.tsx + ├── components/ + │ └── auth-button.tsx // [!code ++] ├── db/ │ ├── index.ts │ └── schema/ │ └── auth.ts ├── lib/ - │ ├── auth/ - │ │ ├── client.ts // [!code ++] - │ │ └── index.ts // [!code ++] + │ └── auth/ + │ ├── client.ts // [!code ++] + │ └── index.ts // [!code ++] └── routes/ - ├── api/ - │ └── auth/ - │ └── $.ts // [!code ++] - ├── components/ - │ └── auth-button.tsx // [!code ++] ├── __root.tsx ├── globals.css - └── index.tsx + ├── index.tsx + └── api/ + └── auth/ + └── $.ts // [!code ++] ``` ### 5. Generate Database Schema @@ -446,26 +446,26 @@ Updated project structure: ├── README.md ├── tsconfig.json ├── vite.config.ts -└── src/ +└── src/ ├── router.tsx + ├── components/ + │ └── auth-button.tsx ├── db/ │ ├── index.ts │ └── schema/ │ └── auth.ts ├── lib/ - │ ├── auth/ - │ │ ├── client.ts - │ │ └── index.ts - ├── components/ - │ └── auth-button.tsx + │ └── auth/ + │ ├── client.ts + │ └── index.ts └── routes/ - ├── api/ - │ └── auth/ - │ └── $.ts ├── __root.tsx ├── dashboard.tsx // [!code ++] ├── globals.css - └── index.tsx + ├── index.tsx + └── api/ + └── auth/ + └── $.ts ``` ### 7. Verify the Implementation From 3e58dec54db4ea599223dc6f6003030587b37a2d Mon Sep 17 00:00:00 2001 From: Neeraj Dalal Date: Tue, 3 Jun 2025 18:50:28 +0530 Subject: [PATCH 11/11] docs: tweaks > integrate-better-auth.md docs/start/framework/react/integrate-better-auth.md --- docs/start/framework/react/integrate-better-auth.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/start/framework/react/integrate-better-auth.md b/docs/start/framework/react/integrate-better-auth.md index 4dcbddc076..ddc362a174 100644 --- a/docs/start/framework/react/integrate-better-auth.md +++ b/docs/start/framework/react/integrate-better-auth.md @@ -292,8 +292,14 @@ export default function Component() {