diff --git a/packages/cta-engine/templates/react/add-on/better-auth/README.md b/packages/cta-engine/templates/react/add-on/better-auth/README.md new file mode 100644 index 0000000..ca30da0 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/README.md @@ -0,0 +1,5 @@ +## Setting up Better Auth + +- Set the `BETTER_AUTH_SECRET` and `BETTER_AUTH_URL` in your `.env.local`. +- if you are using pnpm or deno, make sure `better-sqlite3` post install script is run +- Run `npx @better-auth/cli migrate` diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/_dot_env.local.append b/packages/cta-engine/templates/react/add-on/better-auth/assets/_dot_env.local.append new file mode 100644 index 0000000..1dab5a3 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/_dot_env.local.append @@ -0,0 +1,5 @@ +# Better Auth Secret can be anything, preferable a random string +BETTER_AUTH_SECRET= + +# Backend URL +BETTER_AUTH_URL=http://localhost:3000 \ No newline at end of file diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/integrations/better-auth/header-user.tsx b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/integrations/better-auth/header-user.tsx new file mode 100644 index 0000000..06e9d7d --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/integrations/better-auth/header-user.tsx @@ -0,0 +1,38 @@ +import { authClient } from "@/lib/auth-client"; + +export default function HeaderUser() { + return ( +
+ + +
+ ); +} + +function Avatar() { + const { data } = authClient.useSession(); + const user = data?.user; + if (!user) return null; + return ( +
+ + {user.name.slice(0, 2)} + +
+ ); +} + +function LogoutButton() { + const { data } = authClient.useSession(); + const session = data?.session; + if (!session) return null; + return ( + + ); +} diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/auth-client.ts b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/auth-client.ts new file mode 100644 index 0000000..41e8b9c --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/auth-client.ts @@ -0,0 +1,3 @@ +import { createAuthClient } from "better-auth/react" + +export const authClient = createAuthClient() diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/auth.ts b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/auth.ts new file mode 100644 index 0000000..6f1c6a0 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/auth.ts @@ -0,0 +1,17 @@ +import { betterAuth } from "better-auth"; +import { db } from "./db"; + +export const auth = betterAuth({ + // This example uses local sqlite database + database: db, + emailAndPassword: { + enabled: true + }, + socialProviders: { + // You can add more providers here, check the documentation for more details + // github: { + // clientId: "", + // clientSecret: "" + // } + } +}) \ No newline at end of file diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/db.ts b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/db.ts new file mode 100644 index 0000000..d4900c4 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/lib/db.ts @@ -0,0 +1,3 @@ +import Database from "better-sqlite3"; + +export const db = new Database("./sqlite.db"); \ No newline at end of file diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/api.auth.$.ts b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/api.auth.$.ts new file mode 100644 index 0000000..afdbafc --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/api.auth.$.ts @@ -0,0 +1,11 @@ +import { auth } from '@/lib/auth' +import { createAPIFileRoute } from '@tanstack/react-start/api' + +export const APIRoute = createAPIFileRoute('/api/auth/$')({ + GET: ({ request }) => { + return auth.handler(request) + }, + POST: ({ request }) => { + return auth.handler(request) + }, +}); \ No newline at end of file diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.login.tsx b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.login.tsx new file mode 100644 index 0000000..653fa66 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.login.tsx @@ -0,0 +1,92 @@ +import { authClient } from "@/lib/auth-client"; +import { createFileRoute, Link } from "@tanstack/react-router"; +import { useState } from "react"; + +export const Route = createFileRoute("/demo/better-auth/login")({ + component: RouteComponent, +}); + +function RouteComponent() { + const { data, isPending } = authClient.useSession(); + const session = data?.session; + const [error, setError] = useState(null); + const handleSubmit = (e: React.FormEvent) => { + const formData = new FormData(e.currentTarget); + e.preventDefault(); + const email = formData.get("email") as string; + const password = formData.get("password") as string; + authClient.signIn.email( + { + email, + password, + }, + { + onError(context) { + setError(context.error.message); + }, + onSuccess() { + e.currentTarget.reset(); + }, + }, + ); + }; + return ( + <> +

+ Sign in to your account +

+
+
+ + +
+
+ + +
+ + {session &&

You are signed in

} + {error &&

{error}

} +

+ Don't have an account yet?{" "} + + Sign up + +

+
+ + ); +} diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.signup.tsx b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.signup.tsx new file mode 100644 index 0000000..d71d6f6 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.signup.tsx @@ -0,0 +1,94 @@ +import { authClient } from "@/lib/auth-client"; +import { createFileRoute, Link } from "@tanstack/react-router"; +import { useState } from "react"; + +export const Route = createFileRoute("/demo/better-auth/signup")({ + component: RouteComponent, +}); + +function RouteComponent() { + const { data, isPending } = authClient.useSession(); + const session = data?.session; + const [error, setError] = useState(null); + const handleSubmit = (e: React.FormEvent) => { + const formData = new FormData(e.currentTarget); + e.preventDefault(); + const email = formData.get("email") as string; + const password = formData.get("password") as string; + const name = (formData.get("email") as string)?.split("@")[0]; + authClient.signUp.email( + { + email, + password, + name, + }, + { + onError(context) { + setError(context.error.message); + }, + onSuccess() { + e.currentTarget.reset(); + }, + }, + ); + }; + return ( + <> +

+ Sign up to your account +

+
+
+ + +
+
+ + +
+ + {session &&

You are signed in

} + {error &&

{error}

} +

+ Already have an account?{" "} + + Sign in + +

+
+ + ); +} diff --git a/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.tsx b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.tsx new file mode 100644 index 0000000..9cf59c1 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/assets/src/routes/demo.better-auth.tsx @@ -0,0 +1,17 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/demo/better-auth")({ + component: RouteComponent, +}); + +function RouteComponent() { + return ( +
+
+ +
+
+ ); +} + + diff --git a/packages/cta-engine/templates/react/add-on/better-auth/info.json b/packages/cta-engine/templates/react/add-on/better-auth/info.json new file mode 100644 index 0000000..1ddf10b --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/info.json @@ -0,0 +1,14 @@ +{ + "name": "Better Auth", + "description": "Add Better Auth authentication to your application.", + "phase": "add-on", + "templates": ["file-router"], + "link": "https://www.better-auth.com", + "routes": [ + { + "url": "/demo/better-auth/signup", + "name": "Better Auth" + } + ], + "dependsOn": ["start"] +} diff --git a/packages/cta-engine/templates/react/add-on/better-auth/package.json b/packages/cta-engine/templates/react/add-on/better-auth/package.json new file mode 100644 index 0000000..7cb1fb8 --- /dev/null +++ b/packages/cta-engine/templates/react/add-on/better-auth/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "better-auth": "^1.2.7", + "better-sqlite3": "^11.9.1" + } +}