mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-10 12:27:44 +00:00
docs: resource reference page (#2357)
This commit is contained in:
committed by
GitHub
parent
7ff8671c69
commit
c140af64f9
56
docs/components/resource-card.tsx
Normal file
56
docs/components/resource-card.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { ArrowUpRight } from "lucide-react";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
interface ResourceCardProps {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
href: string;
|
||||||
|
tags?: string[];
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ResourceCard({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
href,
|
||||||
|
tags,
|
||||||
|
className,
|
||||||
|
}: ResourceCardProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"relative flex justify-between rounded-none flex-col group space-y-1 border transition-colors hover:bg-muted/80",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<ArrowUpRight className="absolute top-3 right-3 h-4 w-4 group-hover:opacity-100 opacity-80 text-muted-foreground transition-colors group-hover:text-foreground no-underline underline-offset-0" />
|
||||||
|
<div className="p-4 py-0 flex items-start justify-between">
|
||||||
|
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||||
|
<h3 className="font-semibold tracking-tight no-underline">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
dangerouslySetInnerHTML={{ __html: `${description}` }}
|
||||||
|
className="p-4 py-0 text-sm md:decoration-none text-muted-foreground"
|
||||||
|
></p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{tags && tags.length > 0 && (
|
||||||
|
<div className="py-3 border-zinc-700/80 border-t-[1.2px] flex flex-wrap items-end gap-2">
|
||||||
|
{tags.map((tag) => (
|
||||||
|
<span
|
||||||
|
key={tag}
|
||||||
|
className="inline-flex items-end underline underline-offset-2 rounded-md bg-secondary/10 px-2 py-1 text-xs font-medium text-secondary-foreground"
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
22
docs/components/resource-grid.tsx
Normal file
22
docs/components/resource-grid.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { ResourceCard } from "./resource-card";
|
||||||
|
|
||||||
|
interface ResourceGridProps {
|
||||||
|
resources: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
href: string;
|
||||||
|
tags?: string[];
|
||||||
|
}[];
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ResourceGrid({ resources, className }: ResourceGridProps) {
|
||||||
|
return (
|
||||||
|
<div className={cn("grid gap-4 sm:grid-cols-2 lg:grid-cols-3", className)}>
|
||||||
|
{resources.map((resource) => (
|
||||||
|
<ResourceCard key={resource.href} {...resource} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
65
docs/components/resource-section.tsx
Normal file
65
docs/components/resource-section.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
"use client";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ResourceCard } from "./resource-card";
|
||||||
|
|
||||||
|
interface Resource {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
href: string;
|
||||||
|
tags: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResourceProps {
|
||||||
|
resources: Resource[];
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Resource({ className, resources }: ResourceProps) {
|
||||||
|
const [activeTag, setActiveTag] = useState<string | null>(null);
|
||||||
|
const tags = Array.from(
|
||||||
|
new Set(resources.flatMap((resource) => resource.tags)),
|
||||||
|
);
|
||||||
|
const filterResources = (activeTag: string | null): Resource[] => {
|
||||||
|
if (!activeTag) return resources;
|
||||||
|
return resources.filter((resource) => resource.tags.includes(activeTag));
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={cn("space-y-4", className)}>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveTag(null)}
|
||||||
|
className={cn(
|
||||||
|
"inline-flex items-center rounded-md px-3 py-1 text-sm font-medium transition-colors",
|
||||||
|
activeTag === null
|
||||||
|
? "bg-primary text-primary-foreground"
|
||||||
|
: "bg-secondary/10 text-secondary-foreground hover:bg-secondary/20",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
All
|
||||||
|
</button>
|
||||||
|
{tags.map((tag) => (
|
||||||
|
<button
|
||||||
|
key={tag}
|
||||||
|
onClick={() => setActiveTag(tag)}
|
||||||
|
className={cn(
|
||||||
|
"inline-flex items-center rounded-md px-3 py-1 text-sm font-medium transition-colors",
|
||||||
|
activeTag === tag
|
||||||
|
? "bg-primary text-primary-foreground"
|
||||||
|
: "bg-secondary/10 text-secondary-foreground hover:bg-secondary/20",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mt-2">
|
||||||
|
{filterResources(activeTag).map((resource) => (
|
||||||
|
<ResourceCard key={resource.href} {...resource} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
UserSquare2,
|
UserSquare2,
|
||||||
Database,
|
Database,
|
||||||
KeyRound,
|
KeyRound,
|
||||||
|
Book,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { ReactNode, SVGProps } from "react";
|
import { ReactNode, SVGProps } from "react";
|
||||||
import { Icons } from "./icons";
|
import { Icons } from "./icons";
|
||||||
@@ -1719,6 +1720,11 @@ C0.7,239.6,62.1,0.5,62.2,0.4c0,0,54,13.8,119.9,30.8S302.1,62,302.2,62c0.2,0,0.2,
|
|||||||
</svg>
|
</svg>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Resources",
|
||||||
|
href: "/docs/reference/resources",
|
||||||
|
icon: () => <Book className="w-4 h-4 text-current" />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Security",
|
title: "Security",
|
||||||
href: "/docs/reference/security",
|
href: "/docs/reference/security",
|
||||||
|
|||||||
98
docs/content/docs/reference/resources.mdx
Normal file
98
docs/content/docs/reference/resources.mdx
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
title: Resources
|
||||||
|
description: A curated collection of resources to help you learn and master Better Auth.
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Resource } from "@/components/resource-section";
|
||||||
|
|
||||||
|
A curated collection of resources to help you learn and master Better Auth. From blog posts to video tutorials, find everything you need to get started.
|
||||||
|
|
||||||
|
## Video tutorials
|
||||||
|
|
||||||
|
<Resource resources={
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: "The State of Authentication",
|
||||||
|
description:
|
||||||
|
"<strong>Theo(t3.gg)</strong> explores the current landscape of authentication, discussing trends, challenges, and where the industry is heading.",
|
||||||
|
href: "https://www.youtube.com/watch?v=lxslnp-ZEMw",
|
||||||
|
tags: ["trends", "showcase", "review"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Last Authentication You Will Ever Need",
|
||||||
|
description:
|
||||||
|
"A comprehensive tutorial demonstrating why Better Auth could be the final authentication solution you'll need for your projects.",
|
||||||
|
href: "https://www.youtube.com/watch?v=hFtufpaMcLM",
|
||||||
|
tags: ["implementation", "showcase"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "This Might Be My New Favourite Auth Library",
|
||||||
|
description:
|
||||||
|
"<strong>developedbyed</strong> explores the features and capabilities of Better Auth, explaining why it stands out among authentication libraries.",
|
||||||
|
href: "https://www.youtube.com/watch?v=Hjs3zM7o7NE",
|
||||||
|
tags: ["review", "showcase"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Nextjs 15 Authentication Made EASY with Better Auth",
|
||||||
|
description:
|
||||||
|
"A practical guide showing how to seamlessly integrate Better Auth with Next.js 15 for robust authentication.",
|
||||||
|
href: "https://www.youtube.com/watch?v=lxslnp-ZEMw",
|
||||||
|
tags: ["nextjs", "implementation", "tutorial"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Best authentication framework for next.js",
|
||||||
|
description:
|
||||||
|
"A detailed comparison of authentication frameworks for Next.js, highlighting why Better Auth might be your best choice.",
|
||||||
|
href: "https://www.youtube.com/watch?v=V--T0q9FrEw",
|
||||||
|
tags: ["nextjs", "comparison"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Better-Auth: A First Look",
|
||||||
|
description:
|
||||||
|
"An introductory overview and demonstration of Better Auth's core features and capabilities.",
|
||||||
|
href: "https://www.youtube.com/watch?v=2cQTV6NYxis",
|
||||||
|
tags: ["implementation", "showcase"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Stripe was never so easy (with better auth)",
|
||||||
|
description: "A tutorial on how to integrate Stripe with Better Auth.",
|
||||||
|
href: "https://www.youtube.com/watch?v=g-RIrzBEX6M",
|
||||||
|
tags: [ "implementation"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} />
|
||||||
|
|
||||||
|
## Blog posts
|
||||||
|
|
||||||
|
<Resource resources={
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: "Better Auth with Hono, Bun, TypeScript, React and Vite",
|
||||||
|
description:
|
||||||
|
"You'll learn how to implement authentication with Better Auth in a client - server architecture, where the frontend is separate from the backend.",
|
||||||
|
href: "https://catalins.tech/better-auth-with-hono-bun-typescript-react-vite",
|
||||||
|
tags: ["typescript", "react", "bun", "vite"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Polar.sh + BetterAuth for Organizations",
|
||||||
|
description:
|
||||||
|
"Polar.sh is a platform for building payment integrations. This article will show you how to use Better Auth to authenticate your users.",
|
||||||
|
href: "https://dev.to/phumudzosly/polarsh-betterauth-for-organizations-1j1b",
|
||||||
|
tags: ["organizations", "integration", "payments"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Authenticating users in Astro with Better Auth",
|
||||||
|
description:
|
||||||
|
"Step by step guide on how to authenticate users in Astro with Better Auth.",
|
||||||
|
href: "https://www.launchfa.st/blog/astro-better-auth",
|
||||||
|
tags: ["astro", "integration", "tutorial"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Building Multi-Tenant Apps With Better-Auth and ZenStack",
|
||||||
|
description:
|
||||||
|
"Learn how to build multi-tenant apps with Better-Auth and ZenStack.",
|
||||||
|
href: "https://zenstack.dev/blog/better-auth",
|
||||||
|
tags: ["multi-tenant", "zenstack", "architecture"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} />
|
||||||
Reference in New Issue
Block a user