mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 11:24:57 -05:00
docs: smooth animation for sidebar links and changelogs (#336)
This commit is contained in:
Vendored
+4
-6
@@ -1,6 +1,4 @@
|
||||
import type { GetOutput } from "fumadocs-mdx/config";
|
||||
export declare const changelog: GetOutput<
|
||||
typeof import("../source.config.ts").changelog
|
||||
>;
|
||||
export declare const docs: GetOutput<typeof import("../source.config.ts").docs>;
|
||||
export declare const meta: GetOutput<typeof import("../source.config.ts").meta>;
|
||||
import type { GetOutput } from "fumadocs-mdx/config"
|
||||
export declare const changelog: GetOutput<typeof import("../source.config.ts").changelog>
|
||||
export declare const docs: GetOutput<typeof import("../source.config.ts").docs>
|
||||
export declare const meta: GetOutput<typeof import("../source.config.ts").meta>
|
||||
+60
-336
File diff suppressed because one or more lines are too long
@@ -1,30 +1,38 @@
|
||||
// source.config.ts
|
||||
import { defineCollections, defineDocs } from "fumadocs-mdx/config";
|
||||
import {
|
||||
defineCollections,
|
||||
defineDocs
|
||||
} from "fumadocs-mdx/config";
|
||||
import { defineConfig } from "fumadocs-mdx/config";
|
||||
import { remarkInstall } from "fumadocs-docgen";
|
||||
import { z } from "zod";
|
||||
var source_config_default = defineConfig({
|
||||
mdxOptions: {
|
||||
remarkPlugins: [
|
||||
[
|
||||
remarkInstall,
|
||||
{
|
||||
persist: {
|
||||
id: "persist-install",
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
mdxOptions: {
|
||||
remarkPlugins: [
|
||||
[
|
||||
remarkInstall,
|
||||
{
|
||||
persist: {
|
||||
id: "persist-install"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
});
|
||||
var changelog = defineCollections({
|
||||
type: "doc",
|
||||
dir: "./content/changelog",
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
}),
|
||||
type: "doc",
|
||||
dir: "./content/changelog",
|
||||
schema: z.object({
|
||||
title: z.string()
|
||||
})
|
||||
});
|
||||
var { docs, meta } = defineDocs({
|
||||
dir: "./content/docs",
|
||||
dir: "./content/docs"
|
||||
});
|
||||
export { changelog, source_config_default as default, docs, meta };
|
||||
export {
|
||||
changelog,
|
||||
source_config_default as default,
|
||||
docs,
|
||||
meta
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
export function BookIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||
return (
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
||||
<path d="M7 3.41a1 1 0 0 0-.668-.943L2.275 1.039a.987.987 0 0 0-.877.166c-.25.192-.398.493-.398.812V12.2c0 .454.296.853.725.977l3.948 1.365A1 1 0 0 0 7 13.596V3.41ZM9 13.596a1 1 0 0 0 1.327.946l3.948-1.365c.429-.124.725-.523.725-.977V2.017c0-.32-.147-.62-.398-.812a.987.987 0 0 0-.877-.166L9.668 2.467A1 1 0 0 0 9 3.41v10.186Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function GitHubIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||
return (
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
||||
<path d="M8 .198a8 8 0 0 0-8 8 7.999 7.999 0 0 0 5.47 7.59c.4.076.547-.172.547-.384 0-.19-.007-.694-.01-1.36-2.226.482-2.695-1.074-2.695-1.074-.364-.923-.89-1.17-.89-1.17-.725-.496.056-.486.056-.486.803.056 1.225.824 1.225.824.714 1.224 1.873.87 2.33.666.072-.518.278-.87.507-1.07-1.777-.2-3.644-.888-3.644-3.954 0-.873.31-1.586.823-2.146-.09-.202-.36-1.016.07-2.118 0 0 .67-.214 2.2.82a7.67 7.67 0 0 1 2-.27 7.67 7.67 0 0 1 2 .27c1.52-1.034 2.19-.82 2.19-.82.43 1.102.16 1.916.08 2.118.51.56.82 1.273.82 2.146 0 3.074-1.87 3.75-3.65 3.947.28.24.54.73.54 1.48 0 1.07-.01 1.93-.01 2.19 0 .21.14.46.55.38A7.972 7.972 0 0 0 16 8.199a8 8 0 0 0-8-8Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function FeedIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||
return (
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M2.5 3a.5.5 0 0 1 .5-.5h.5c5.523 0 10 4.477 10 10v.5a.5.5 0 0 1-.5.5h-.5a.5.5 0 0 1-.5-.5v-.5A8.5 8.5 0 0 0 3.5 4H3a.5.5 0 0 1-.5-.5V3Zm0 4.5A.5.5 0 0 1 3 7h.5A5.5 5.5 0 0 1 9 12.5v.5a.5.5 0 0 1-.5.5H8a.5.5 0 0 1-.5-.5v-.5a4 4 0 0 0-4-4H3a.5.5 0 0 1-.5-.5v-.5Zm0 5a1 1 0 1 1 2 0 1 1 0 0 1-2 0Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function XIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||
return (
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
||||
<path d="M9.51762 6.77491L15.3459 0H13.9648L8.90409 5.88256L4.86212 0H0.200195L6.31244 8.89547L0.200195 16H1.58139L6.92562 9.78782L11.1942 16H15.8562L9.51728 6.77491H9.51762ZM7.62588 8.97384L7.00658 8.08805L2.07905 1.03974H4.20049L8.17706 6.72795L8.79636 7.61374L13.9654 15.0075H11.844L7.62588 8.97418V8.97384Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { AnimatePresence } from "@/components/ui/fade-in";
|
||||
|
||||
const ChangelogOne = () => {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
|
||||
<img
|
||||
src="https://camo.githubusercontent.com/3282afc585d07e52e883ac2345467841e5c9cbe3befdec9dd6f84c603748e0d4/68747470733a2f2f726573656e642e636f6d2f5f6e6578742f696d6167653f75726c3d253246737461746963253246706f737473253246776562686f6f6b732e6a706726773d36343026713d3735"
|
||||
className="w-full h-[400px] rounded-lg"
|
||||
/>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-2xl font-bold tracking-tighter">
|
||||
Commit message suggestions
|
||||
</h2>
|
||||
<hr className="h-px bg-gray-200 w-full" />
|
||||
</div>
|
||||
<p className="text-gray-300 text-[0.855rem]">
|
||||
In the latest release, I've added support for commit message and
|
||||
description suggestions via an integration with OpenAI. Commit looks
|
||||
at all of your changes, and feeds that into the machine with a bit of
|
||||
prompt-tuning to get back a commit message that does a surprisingly
|
||||
good job at describing the intent of your changes. It's also been a
|
||||
pretty helpful way to remind myself what the hell I was working on at
|
||||
the end of the day yesterday when I get back to my computer and
|
||||
realize I didn't commit any of my work.
|
||||
</p>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h4 className="text-xl tracking-tighter"> Improvement</h4>
|
||||
<hr className="h-px bg-gray-200 w-full" />
|
||||
</div>
|
||||
|
||||
<ul className="list-disc ml-10 text-[0.855rem]">
|
||||
<li>
|
||||
Added commit message and description suggestions powered by OpenAI
|
||||
</li>
|
||||
<li>
|
||||
Started commit message and description suggestions powered by OpenAI
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Restored message and description suggestions powered by OpenAI
|
||||
</li>
|
||||
<li>
|
||||
Added commit message and description suggestions powered by OpenAI
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
export default ChangelogOne;
|
||||
@@ -1,36 +0,0 @@
|
||||
import { AnimatePresence } from "@/components/ui/fade-in";
|
||||
|
||||
const listOfFeatures = [
|
||||
"Multiple framework support",
|
||||
"Email & Password Authentication",
|
||||
"OAuth Authentication",
|
||||
"Account & Session Management",
|
||||
"Rate Limiting",
|
||||
"Multiple Plugins",
|
||||
"Migration CLI",
|
||||
"Multiple Plugins",
|
||||
"And more...",
|
||||
];
|
||||
|
||||
const ChangelogOne = () => {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-2xl font-bold tracking-tighter">Beta Release</h2>
|
||||
<p>The first beta release of better-auth is now available!</p>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 text-[0.855rem]"></p>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h4 className="text-xl tracking-tighter">Features</h4>
|
||||
</div>
|
||||
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
|
||||
{listOfFeatures.map((change, i) => (
|
||||
<li key={i}>{change}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
export default ChangelogOne;
|
||||
@@ -1,48 +0,0 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { AnimatePresence } from "@/components/ui/fade-in";
|
||||
import Link from "next/link";
|
||||
|
||||
const listOfFeatures = [
|
||||
"Database adapters support including prisma, drizzle and mongo db.",
|
||||
"Database hooks",
|
||||
"CrossDomain cookies",
|
||||
"onRequest and onResponse plugin hooks",
|
||||
"init interface for plugins",
|
||||
];
|
||||
|
||||
const ChangelogOne = () => {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-2xl font-bold tracking-tighter">v0.2.0</h2>
|
||||
<p>
|
||||
We have added support for database adapters including prisma,
|
||||
drizzle and mongo db and other changes.
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 text-[0.855rem]"></p>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h4 className="text-xl tracking-tighter">Changes</h4>
|
||||
</div>
|
||||
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
|
||||
{listOfFeatures.map((change, i) => (
|
||||
<li key={i}>{change}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p>
|
||||
see{" "}
|
||||
<Link href="https://github.com/better-auth/better-auth/releases/tag/v0.2.0">
|
||||
Changelog
|
||||
</Link>
|
||||
for full list of changes.
|
||||
</p>
|
||||
<Badge variant="secondary">
|
||||
🚧 We still in beta and we don't recommend to use better-auth in
|
||||
production just yet.
|
||||
</Badge>
|
||||
</div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
export default ChangelogOne;
|
||||
@@ -1,56 +0,0 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { AnimatePresence } from "@/components/ui/fade-in";
|
||||
import Link from "next/link";
|
||||
|
||||
const listOfFeatures = [
|
||||
"Database Schema Generation",
|
||||
"Phone Number Plugin",
|
||||
"Anonymous Plugin",
|
||||
"Better type Inference",
|
||||
"User Delete API",
|
||||
"Custom table/model names",
|
||||
"Removed flat db config",
|
||||
"new core table for verification use cases",
|
||||
"moved passkey challenge keys to be stored on db ",
|
||||
"and many bug fixes and improvements",
|
||||
];
|
||||
|
||||
const ChangelogThree = () => {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-2xl font-bold tracking-tighter">v0.3.0</h2>
|
||||
<p>
|
||||
Database Schema Generation, Phone Number Plugin, Anonymous Plugin,
|
||||
Better type Inference, Custom table names, and many more.
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 text-[0.855rem]"></p>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h4 className="text-xl tracking-tighter">Features & Changes</h4>
|
||||
</div>
|
||||
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
|
||||
{listOfFeatures.map((change, i) => (
|
||||
<li key={i}>{change}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p>
|
||||
see{" "}
|
||||
<Link
|
||||
href="https://github.com/better-auth/better-auth/releases/tag/v0.3.0"
|
||||
className="underline"
|
||||
>
|
||||
release note{" "}
|
||||
</Link>
|
||||
for full list of changes.
|
||||
</p>
|
||||
<Badge variant="secondary">
|
||||
🚧 We still in beta and we don't recommend to use better-auth in
|
||||
production just yet.
|
||||
</Badge>
|
||||
</div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
export default ChangelogThree;
|
||||
@@ -1,20 +0,0 @@
|
||||
import ChangeLogTwo from "./2024-09-29";
|
||||
import ChangelogOne from "./2024-09-28";
|
||||
import ChangeLogThree from "./2024-10-04";
|
||||
export const Logs = [
|
||||
{
|
||||
name: "Changelog 3",
|
||||
date: "2024-10-04",
|
||||
component: ChangeLogThree,
|
||||
},
|
||||
{
|
||||
name: "Changelog 2",
|
||||
date: "2024-09-29",
|
||||
component: ChangeLogTwo,
|
||||
},
|
||||
{
|
||||
name: "Changelog 1",
|
||||
date: "2024-09-28",
|
||||
component: ChangelogOne,
|
||||
},
|
||||
];
|
||||
@@ -1,112 +0,0 @@
|
||||
import { Layout } from "./_components/_layout";
|
||||
import { useId } from "react";
|
||||
|
||||
import { Intro, IntroFooter } from "./_components/changelog-layout";
|
||||
import { StarField } from "./_components/stat-field";
|
||||
|
||||
function Timeline() {
|
||||
let id = useId();
|
||||
|
||||
return (
|
||||
<div className="pointer-events-none absolute inset-0 z-50 overflow-hidden lg:right-[calc(max(2rem,50%-38rem)+40rem)] lg:min-w-[32rem] lg:overflow-visible">
|
||||
<svg
|
||||
className="absolute left-[max(0px,calc(50%-18.125rem))] top-0 h-full w-1.5 lg:left-full lg:ml-1 xl:left-auto xl:right-1 xl:ml-0"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<defs>
|
||||
<pattern id={id} width="6" height="8" patternUnits="userSpaceOnUse">
|
||||
<path
|
||||
d="M0 0H6M0 8H6"
|
||||
className="stroke-sky-900/10 xl:stroke-white/10 dark:stroke-white/10"
|
||||
fill="none"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill={`url(#${id})`} />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Glow() {
|
||||
let id = useId();
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 -z-10 overflow-hidden bg-gradient-to-tr from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10 lg:right-[calc(max(2rem,50%-38rem)+40rem)] lg:min-w-[32rem]">
|
||||
<svg
|
||||
className="absolute -bottom-48 left-[-40%] h-[80rem] w-[180%] lg:-right-40 lg:bottom-auto lg:left-auto lg:top-[-40%] lg:h-[180%] lg:w-[80rem]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<defs>
|
||||
<radialGradient id={`${id}-desktop`} cx="100%">
|
||||
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.4)" />
|
||||
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
|
||||
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
|
||||
</radialGradient>
|
||||
<radialGradient id={`${id}-mobile`} cy="100%">
|
||||
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.3)" />
|
||||
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
|
||||
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill={`url(#${id}-desktop)`}
|
||||
className="hidden lg:block"
|
||||
/>
|
||||
<rect
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill={`url(#${id}-mobile)`}
|
||||
className="lg:hidden"
|
||||
/>
|
||||
</svg>
|
||||
<div className="absolute inset-x-0 bottom-0 right-0 h-px dark:bg-white/5 mix-blend-overlay lg:left-auto lg:top-0 lg:h-auto lg:w-px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FixedSidebar({
|
||||
main,
|
||||
footer,
|
||||
}: {
|
||||
main: React.ReactNode;
|
||||
footer: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="relative flex-none overflow-hidden px-10 lg:pointer-events-none md:fixed lg:inset-0 lg:z-40 lg:flex lg:px-0">
|
||||
<Glow />
|
||||
<div className="relative flex w-full lg:pointer-events-auto lg:mr-[calc(max(2rem,50%-35rem)+40rem)] lg:min-w-[32rem] lg:overflow-y-auto lg:overflow-x-hidden lg:pl-[max(4rem,calc(50%-44rem))]">
|
||||
<div className="mx-auto pr-20 max-w-lg lg:mx-auto lg:flex lg:max-w-4xl lg:flex-col lg:before:flex-1 lg:before:pt-6">
|
||||
<div className="pb-16 pt-20 sm:pb-20 sm:pt-32 lg:py-20">
|
||||
<div className="relative ">
|
||||
<StarField className="-right-44 top-14" />
|
||||
{main}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-1 items-end justify-center pb-4 lg:justify-start lg:pb-6">
|
||||
{footer}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const ChangeLogLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<div className="h-full font-sans overflow-y-auto">
|
||||
<FixedSidebar main={<Intro />} footer={<IntroFooter />} />
|
||||
<div />
|
||||
<div className="relative overflow-y-auto flex gap-2 justify-start items-start">
|
||||
<Timeline />
|
||||
<div className="space-y-20 py-20 w-[80%] mx-auto md:mx-0 md:ml-auto md:w-1/2 h-screen sm:space-y-20 sm:py-20">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChangeLogLayout;
|
||||
+140
-17
@@ -1,25 +1,148 @@
|
||||
import { AnimatePresence } from "@/components/ui/fade-in";
|
||||
import { Logs } from "./_logs";
|
||||
import { FormattedDate } from "./_components/fmt-dates";
|
||||
import Link from "next/link";
|
||||
import { useId } from "react";
|
||||
|
||||
import { changelog } from "@/app/source";
|
||||
import { notFound } from "next/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { IconLink } from "./_components/changelog-layout";
|
||||
import { BookIcon, GitHubIcon, XIcon } from "./_components/icons";
|
||||
import { DiscordLogoIcon } from "@radix-ui/react-icons";
|
||||
import { StarField } from "./_components/stat-field";
|
||||
|
||||
const ChangelogPage = () => {
|
||||
// @ts-ignore
|
||||
const page = changelog.getPage();
|
||||
|
||||
if (page == null) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mt-10 overflow-visible h-full flex flex-col gap-10">
|
||||
{Logs.map((log) => {
|
||||
return (
|
||||
<div className="relative my-5 h-auto">
|
||||
<div className="sticky top-2 flex-1 h-full">
|
||||
<FormattedDate
|
||||
className="absolute md:-left-36 left-0 text-sm -top-8 md:top-0 font-light"
|
||||
date={log.date}
|
||||
<div className="grid md:grid-cols-2 items-start">
|
||||
<div className="bg-gradient-to-tr overflow-hidden px-12 py-24 md:py-0 -mt-[100px] md:h-dvh relative md:sticky top-0 from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10">
|
||||
<StarField className="top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2" />
|
||||
<Glow />
|
||||
|
||||
<div className="flex flex-col justify-center max-w-xl mx-auto h-full">
|
||||
<h1 className="mt-14 font-sans font-semibold tracking-tighter text-5xl">
|
||||
All of the changes made will be{" "}
|
||||
<span className="">available here.</span>
|
||||
</h1>
|
||||
<p className="mt-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
Better Auth is comprehensive authentication library for TypeScript
|
||||
that provides a wide range of features to make authentication easier
|
||||
and more secure.
|
||||
</p>
|
||||
<hr className="h-px bg-gray-300 mt-5" />
|
||||
<div className="mt-8 flex flex-wrap text-gray-600 dark:text-gray-300 justify-center gap-x-1 gap-y-3 sm:gap-x-2 lg:justify-start">
|
||||
<IconLink
|
||||
href="/docs"
|
||||
icon={BookIcon}
|
||||
className="flex-none text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
Documentation
|
||||
</IconLink>
|
||||
<IconLink
|
||||
href="https://github.com/better-auth/better-auth"
|
||||
icon={GitHubIcon}
|
||||
className="flex-none text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
GitHub
|
||||
</IconLink>
|
||||
<IconLink
|
||||
href="https://discord.gg/GYC3W7tZzb"
|
||||
icon={DiscordLogoIcon}
|
||||
className="flex-none text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
Community
|
||||
</IconLink>
|
||||
</div>
|
||||
<p className="flex items-baseline absolute bottom-4 max-md:left-1/2 max-md:-translate-x-1/2 gap-x-2 text-[0.8125rem]/6 text-gray-500">
|
||||
Brought to you by{" "}
|
||||
<IconLink href="#" icon={XIcon} compact>
|
||||
BETTER-AUTH.
|
||||
</IconLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-4 md:px-8 pb-12 md:py-12">
|
||||
<div className="max-w-2xl">
|
||||
<MDX
|
||||
components={{
|
||||
h2: (props) => (
|
||||
<h2
|
||||
className="text-2xl mt-16 font-bold tracking-tighter"
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
<log.component />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
),
|
||||
h3: (props) => (
|
||||
<h3 className="text-xl tracking-tighter" {...props} />
|
||||
),
|
||||
p: (props) => <p className="my-4" {...props} />,
|
||||
ul: (props) => (
|
||||
<ul
|
||||
className="list-disc ml-10 my-4 text-[0.855rem] text-gray-600 dark:text-gray-300"
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
li: (props) => <li className="my-px" {...props} />,
|
||||
a: ({ className, ...props }: any) => (
|
||||
<Link
|
||||
className={cn("font-medium underline", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
Badge: (props) => (
|
||||
<Badge variant="secondary" className="py-0" {...props} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChangelogPage;
|
||||
|
||||
function Glow() {
|
||||
let id = useId();
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 -z-10 overflow-hidden bg-gradient-to-tr from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10">
|
||||
<svg
|
||||
className="absolute -bottom-48 left-[-40%] h-[80rem] w-[180%] lg:-right-40 lg:bottom-auto lg:left-auto lg:top-[-40%] lg:h-[180%] lg:w-[80rem]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<defs>
|
||||
<radialGradient id={`${id}-desktop`} cx="100%">
|
||||
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.4)" />
|
||||
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
|
||||
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
|
||||
</radialGradient>
|
||||
<radialGradient id={`${id}-mobile`} cy="100%">
|
||||
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.3)" />
|
||||
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
|
||||
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill={`url(#${id}-desktop)`}
|
||||
className="hidden lg:block"
|
||||
/>
|
||||
<rect
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill={`url(#${id}-mobile)`}
|
||||
className="lg:hidden"
|
||||
/>
|
||||
</svg>
|
||||
<div className="absolute inset-x-0 bottom-0 right-0 h-px dark:bg-white/5 mix-blend-overlay lg:left-auto lg:top-0 lg:h-auto lg:w-px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
"use client";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
|
||||
import { AnimatePresence, motion, MotionConfig } from "framer-motion";
|
||||
|
||||
import { AsideLink } from "@/components/ui/aside-link";
|
||||
import { FadeIn, FadeInStagger } from "@/components/ui/fade-in";
|
||||
import { Suspense, useEffect, useState } from "react";
|
||||
import { useSearchContext } from "fumadocs-ui/provider";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { contents, examples } from "./sidebar-content";
|
||||
import { Search } from "lucide-react";
|
||||
import { ChevronDownIcon, Search } from "lucide-react";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -20,8 +16,11 @@ import {
|
||||
SelectValue,
|
||||
} from "./ui/select";
|
||||
import { loglib } from "@loglib/tracker";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export default function ArticleLayout() {
|
||||
const [currentOpen, setCurrentOpen] = useState<number>(0);
|
||||
|
||||
const { setOpenSearch } = useSearchContext();
|
||||
const pathname = usePathname();
|
||||
|
||||
@@ -131,58 +130,85 @@ export default function ArticleLayout() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
defaultValue={`item-${getDefaultValue()}`}
|
||||
>
|
||||
{cts.map((item, i) => (
|
||||
<AccordionItem value={`item-${i}`} key={item.title}>
|
||||
<AccordionTrigger className="border-b border-lines px-5 py-2.5 text-left">
|
||||
<div className="flex items-center gap-2">
|
||||
{item.Icon && <item.Icon className="w-5 h-5" />}
|
||||
{item.title}
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className=" space-y-1 p-0">
|
||||
<FadeInStagger faster>
|
||||
{item.list.map((listItem, j) => (
|
||||
<FadeIn
|
||||
key={listItem.title}
|
||||
onClick={() => {
|
||||
loglib.track("sidebar-link-click", {
|
||||
title: listItem.title,
|
||||
href: listItem.href,
|
||||
});
|
||||
}}
|
||||
<MotionConfig transition={{ duration: 0.4, type: "spring", bounce: 0 }}>
|
||||
<div className="flex flex-col">
|
||||
{cts.map((item, index) => (
|
||||
<div key={item.title}>
|
||||
<button
|
||||
className="border-b w-full hover:underline border-lines text-sm px-5 py-2.5 text-left flex items-center gap-2"
|
||||
onClick={() => {
|
||||
if (currentOpen === index) {
|
||||
setCurrentOpen(-1);
|
||||
} else {
|
||||
setCurrentOpen(index);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<item.Icon className="w-5 h-5" />
|
||||
<span className="grow">{item.title}</span>
|
||||
<motion.div
|
||||
animate={{ rotate: currentOpen === index ? 180 : 0 }}
|
||||
>
|
||||
<ChevronDownIcon
|
||||
className={cn(
|
||||
"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200",
|
||||
)}
|
||||
/>
|
||||
</motion.div>
|
||||
</button>
|
||||
<AnimatePresence initial={false}>
|
||||
{currentOpen === index && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: "auto" }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
className="relative overflow-hidden"
|
||||
>
|
||||
<Suspense fallback={<>Loading...</>}>
|
||||
{listItem.group ? (
|
||||
<div className="flex flex-row gap-2 items-center mx-5 my-1 ">
|
||||
<p className="text-sm bg-gradient-to-tr dark:from-gray-100 dark:to-stone-200 bg-clip-text text-transparent from-gray-900 to-stone-900">
|
||||
{listItem.title}
|
||||
</p>
|
||||
<line className="flex-grow h-px bg-gradient-to-r from-stone-800/90 to-stone-800/60" />
|
||||
</div>
|
||||
) : (
|
||||
<AsideLink
|
||||
href={listItem.href}
|
||||
startWith="/docs"
|
||||
title={listItem.title}
|
||||
className="break-words w-[--fd-sidebar-width]"
|
||||
<motion.div
|
||||
// initial={{ opacity: 0, y: -20 }}
|
||||
// animate={{ opacity: 1, y: 0 }}
|
||||
className="text-sm"
|
||||
>
|
||||
{item.list.map((listItem, j) => (
|
||||
<div
|
||||
key={listItem.title}
|
||||
onClick={() => {
|
||||
loglib.track("sidebar-link-click", {
|
||||
title: listItem.title,
|
||||
href: listItem.href,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<listItem.icon className="w-4 h-4 text-stone-950 dark:text-white" />
|
||||
{listItem.title}
|
||||
</AsideLink>
|
||||
)}
|
||||
</Suspense>
|
||||
</FadeIn>
|
||||
))}
|
||||
</FadeInStagger>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</Accordion>
|
||||
<Suspense fallback={<>Loading...</>}>
|
||||
{listItem.group ? (
|
||||
<div className="flex flex-row gap-2 items-center mx-5 my-1 ">
|
||||
<p className="text-sm bg-gradient-to-tr dark:from-gray-100 dark:to-stone-200 bg-clip-text text-transparent from-gray-900 to-stone-900">
|
||||
{listItem.title}
|
||||
</p>
|
||||
<line className="flex-grow h-px bg-gradient-to-r from-stone-800/90 to-stone-800/60" />
|
||||
</div>
|
||||
) : (
|
||||
<AsideLink
|
||||
href={listItem.href}
|
||||
startWith="/docs"
|
||||
title={listItem.title}
|
||||
className="break-words w-[--fd-sidebar-width]"
|
||||
>
|
||||
<listItem.icon className="w-4 h-4 text-stone-950 dark:text-white" />
|
||||
{listItem.title}
|
||||
</AsideLink>
|
||||
)}
|
||||
</Suspense>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</MotionConfig>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Basic Usage
|
||||
description: Getting started with Better Auth
|
||||
---
|
||||
|
||||
## v0.3.0 (Latest)
|
||||
|
||||
Database Schema Generation, Phone Number Plugin, Anonymous Plugin, Better type Inference, Custom table names, and many more.
|
||||
|
||||
### Features & Changes
|
||||
|
||||
- Database Schema Generation
|
||||
- Phone Number Plugin
|
||||
- Anonymous Plugin
|
||||
- Better type Inference
|
||||
- User Delete API
|
||||
- Custom table/model names
|
||||
- Removed flat db config
|
||||
- New core table for verification use cases
|
||||
- Moved passkey challenge keys to be stored on db
|
||||
- Many bug fixes and improvements
|
||||
|
||||
See [release notes](https://github.com/better-auth/better-auth/releases/tag/v0.3.0) for full list of changes.
|
||||
|
||||
<Badge>
|
||||
🚧 We are still in beta and we don't recommend using better-auth in production just yet.
|
||||
</Badge>
|
||||
|
||||
## v0.2.0
|
||||
|
||||
We have added support for database adapters including Prisma, Drizzle, and MongoDB, along with other changes.
|
||||
|
||||
### Changes
|
||||
|
||||
- Database adapters support including Prisma, Drizzle, and MongoDB
|
||||
- Database hooks
|
||||
- Cross-domain cookies
|
||||
- onRequest and onResponse plugin hooks
|
||||
- Init interface for plugins
|
||||
|
||||
See [Changelog](https://github.com/better-auth/better-auth/releases/tag/v0.2.0) for full list of changes.
|
||||
|
||||
<Badge>
|
||||
🚧 We are still in beta and we don't recommend using better-auth in production just yet.
|
||||
</Badge>
|
||||
|
||||
## Beta Release
|
||||
|
||||
The first beta release of better-auth is now available!
|
||||
|
||||
### Features
|
||||
|
||||
- Multiple framework support
|
||||
- Email & Password Authentication
|
||||
- OAuth Authentication
|
||||
- Account & Session Management
|
||||
- Rate Limiting
|
||||
- Multiple Plugins
|
||||
- Migration CLI
|
||||
- And more...
|
||||
|
||||
Reference in New Issue
Block a user