docs: resource reference page (#2357)

This commit is contained in:
KinfeMichael Tariku
2025-04-20 00:53:50 +03:00
committed by GitHub
parent 7ff8671c69
commit c140af64f9
5 changed files with 247 additions and 0 deletions

View 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>
);
}

View 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>
);
}

View 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>
);
}

View File

@@ -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",

View 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"],
},
]
} />