diff --git a/docs/components/Advantages/index.tsx b/docs/components/Advantages/index.tsx new file mode 100644 index 0000000000..ecf543071c --- /dev/null +++ b/docs/components/Advantages/index.tsx @@ -0,0 +1,172 @@ +import { useEffect, useState } from "react" +import { createHighlighter, Highlighter } from "shiki/index.mjs" + +const codeSnippet = `import NextAuth from "next-auth" + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [], +})` + +export default function Advantages() { + const [highlighter, setHighlighter] = useState([]) + + useEffect(() => { + ;(async () => { + const hl = await createHighlighter({ + themes: ["github-light-default", "github-light-default"], + langs: ["ts", "tsx", "bash"], + }) + const h2 = await createHighlighter({ + themes: ["github-dark", "github-dark"], + langs: ["ts", "tsx", "bash"], + }) + setHighlighter([hl, h2]) + })() + }, []) + + const highlightLight = (code: string, lang: "ts" | "tsx" | "bash") => { + if (!highlighter || highlighter.length !== 2) { + return `
${code}
` + } + + return highlighter[0].codeToHtml(code, { + lang, + themes: { + light: "github-light-default", + dark: "github-light-default", + }, + }) + } + + const highlightDark = (code: string, lang: "ts" | "tsx" | "bash") => { + if (!highlighter || highlighter.length !== 2) { + return `
${code}
` + } + return highlighter[1].codeToHtml(code, { + lang, + themes: { + light: "github-dark", + dark: "github-dark", + }, + }) + } + + return ( +
+
+
+
+
+

+ Everything you need, nothing you don’t +

+
+ Auth.js is a complete, open-source authentication solution, + designed to be flexible and secure, giving you full control over + your user data. +
+
+ +
+
+
+
+ + + +
+

+ Use Any Framework +

+
+ Built for the edge with first-class support for Next.js, + SvelteKit, SolidStart, and more. +
+
+ +
+
+ + + +
+

+ Own Your Data +

+
+ Connect to your own database with our adapter system. Never + get locked into a vendor's user table again. +
+
+
+ +
+
+ + + +
+

+ Fully Extensible +

+
+ Choose from 100+ pre-configured providers or add your own. + Customize everything from UI to session handling with callbacks. +
+
+
+ {/* 3. Render the highlighted HTML using dangerouslySetInnerHTML */} +
+
+
+
+
+
+
+
+
+ ) +} diff --git a/docs/components/CTA/index.tsx b/docs/components/CTA/index.tsx new file mode 100644 index 0000000000..becee6ab10 --- /dev/null +++ b/docs/components/CTA/index.tsx @@ -0,0 +1,50 @@ +export default function CTA() { + return ( +
+
+
+

+ Ready to secure your app? +

+
+ Get started in minutes with our quickstart guide or dive into the + documentation to see everything Auth.js has to offer. +
+
+ + Get started + + + See all integrations + +
+ +
+
+
+ ) +} diff --git a/docs/components/Footer/index.tsx b/docs/components/Footer/index.tsx index 3978a4ab8e..61dc609563 100644 --- a/docs/components/Footer/index.tsx +++ b/docs/components/Footer/index.tsx @@ -1,97 +1,82 @@ -import { useEffect } from "react" -import { useRouter } from "next/router" -import cx from "classnames" +import React from "react" -function kFormatter(num: number) { - return (Math.sign(num) * (Math.abs(num) / 1000)).toFixed(1) + "k" +function FooterSection({ children }) { + return
{children}
} -export function Footer({ className = "" }) { - const router = useRouter() - - useEffect(() => { - fetch("https://api.github.com/repos/nextauthjs/next-auth") - .then((res) => res.json()) - .then((data) => { - const githubStat = document.querySelector(".github-counter")! - if (!githubStat) return - githubStat.innerHTML = kFormatter(data.stargazers_count ?? 21100) - }) - - // CarbonAds hydration error workaround hack - const carbonAdsEl = - document.querySelector("#_carbonads_js") - if (carbonAdsEl) { - carbonAdsEl.src = - "https://cdn.carbonads.com/carbon.js?serve=CWYD42JY&placement=authjsdev&format=cover" +function FooterHeading({ children }) { + return ( +

+ {children} +

+ ) +} - router.events.on("routeChangeComplete", () => { - window._carbonads?.refresh() - }) - } - }, []) +function FooterLink({ href, children }) { return ( -
-
-
-

About Auth.js

- -
-
-

Download

-
    - + {children} + + ) +} + +export default function Footer() { + return ( +
    +
    +
    + + About Auth.js + Introduction + Security + + Migrating to v5 + + + + + Documentation + Get Started + + Providers + + + Adapters + + + + + Community + GitHub - - + + + Discord + + NPM - -
+ + + + + Acknowledgements + Clerk (Sponsor) + + Contributors + + Sponsors +
-
-

Acknowledgements

- +
+

+ © {new Date().getFullYear()} Auth.js Team. Balázs Orbán and + Team. All rights reserved. +

-
- Auth.js © Balázs Orbán and Team - {new Date().getFullYear()} -
-
+ ) } - -export default Footer diff --git a/docs/components/Hero/CodeTabs.tsx b/docs/components/Hero/CodeTabs.tsx new file mode 100644 index 0000000000..7f0aad5818 --- /dev/null +++ b/docs/components/Hero/CodeTabs.tsx @@ -0,0 +1,187 @@ +import React, { useState, useEffect } from "react" +import { type Highlighter, createHighlighter } from "shiki" +import Image from "next/image" + +import { RichTabs } from "@/components/RichTabs" +import { CaretRight } from "../Icons" + +// Icons +import expressIcon from "../../public/img/etc/express.svg" +import nextIcon from "../../public/img/etc/nextjs.svg" +import qwikIcon from "../../public/img/etc/qwik.svg" +import sveltekitIcon from "../../public/img/etc/sveltekit.svg" + +const codeSnippets = { + nextjs: `// auth.ts +import NextAuth from "next-auth" +import GitHub from "next-auth/providers/github" +export const { auth, handlers } = NextAuth({ providers: [GitHub] }) + +// middleware.ts +export { auth as middleware } from "@auth" + +// app/api/auth/[...nextauth]/route.ts +import { handlers } from "@auth" +export const { GET, POST } = handlers`, + sveltekit: `// src/auth.ts +import { SvelteKitAuth } from "@auth/sveltekit" +import GitHub from '@auth/sveltekit/providers/github' + +export const { handle } = SvelteKitAuth({ + providers: [GitHub], +}) + +// src/hooks.server.ts +export { handle } from "./auth"`, + express: `// server.ts +import express from "express" +import { ExpressAuth } from "@auth/express" +import GitHub from "@auth/express/providers/github" + +const app = express() + +app.use("/auth/*", ExpressAuth({ providers: [GitHub] }))`, + qwik: `// src/routes/plugin@auth.ts +import { QwikAuth } from "@auth/qwik" +import GitHub from "@auth/qwik/providers/github" +export const { onRequest, useSession } = QwikAuth$(() => ({ providers: [GitHub] }))`, +} + +const ExpressIcon = () => ( + Express +) + +const NextIcon = () => ( + Next.js +) + +const QwikIcon = () => ( + Qwik +) + +const SvelteKitIcon = () => ( + SvelteKit +) + +export const CodeTabs = () => { + const [activeTab, setActiveTab] = useState("nextjs") + const [highlighter, setHighlighter] = useState([]) + + const tabs = [ + { value: "express", Icon: ExpressIcon, name: "Express" }, + { value: "nextjs", Icon: NextIcon, name: "Next.js" }, + { value: "qwik", Icon: QwikIcon, name: "Qwik" }, + { value: "sveltekit", Icon: SvelteKitIcon, name: "SvelteKit" }, + ] + + useEffect(() => { + ;(async () => { + const hl = await createHighlighter({ + themes: ["github-light-default", "github-light-default"], + langs: ["ts", "tsx", "bash"], + }) + const h2 = await createHighlighter({ + themes: ["github-dark", "github-dark"], + langs: ["ts", "tsx", "bash"], + }) + setHighlighter([hl, h2]) + })() + }, []) + + const highlightLight = (code: string, lang: "ts" | "tsx" | "bash") => { + if (!highlighter || highlighter.length !== 2) { + return `
${code}
` + } + return highlighter[0].codeToHtml(code, { + lang, + themes: { + light: "github-light-default", + dark: "github-light-default", + }, + }) + } + + const highlightDark = (code: string, lang: "ts" | "tsx" | "bash") => { + if (!highlighter || highlighter.length !== 2) { + return `
${code}
` + } + return highlighter[1].codeToHtml(code, { + lang, + themes: { + light: "github-dark", + dark: "github-dark", + }, + }) + } + + return ( +
+ +
+ + {tabs.map((tab) => ( + + + + ))} + + + More + + +
+ + {tabs.map((tab) => ( + +
+
+ + ))} + +
+ ) +} diff --git a/docs/components/Hero/index.tsx b/docs/components/Hero/index.tsx new file mode 100644 index 0000000000..efda9644d2 --- /dev/null +++ b/docs/components/Hero/index.tsx @@ -0,0 +1,50 @@ +import Link from "next/link" +import React from "react" +import { CodeTabs } from "./CodeTabs" + +export default function Hero() { + return ( +
+
+
+

+ Auth. Free. Open Source. +

+
+ Own your user data. Connect to your own database with a simple + adapter, any from 100+ providers, and avoid vendor lock-in forever. +
+
+
+ + Get Started + + + + + + Source + +
+
+ +
+ ) +} diff --git a/docs/components/Icons/Artlist.tsx b/docs/components/Icons/Artlist.tsx new file mode 100644 index 0000000000..733b25c91c --- /dev/null +++ b/docs/components/Icons/Artlist.tsx @@ -0,0 +1,16 @@ +type Props = { + className?: string +} + +export function ArtlistIcon({ className }: Props) { + return ( + + + + ) +} diff --git a/docs/components/Icons/CalIcon.tsx b/docs/components/Icons/CalIcon.tsx new file mode 100644 index 0000000000..30136fcc3d --- /dev/null +++ b/docs/components/Icons/CalIcon.tsx @@ -0,0 +1,40 @@ +type Props = { + className?: string +} + +export function CalIcon({ className }: Props) { + return ( + + + + + + + + + + ) +} diff --git a/docs/components/Icons/ChatGPTIcon.tsx b/docs/components/Icons/ChatGPTIcon.tsx new file mode 100644 index 0000000000..f9330f5d74 --- /dev/null +++ b/docs/components/Icons/ChatGPTIcon.tsx @@ -0,0 +1,16 @@ +type Props = { + className?: string +} + +export function ChatGPTIcon({ className }: Props) { + return ( + + + + ) +} diff --git a/docs/components/Icons/DubIcon.tsx b/docs/components/Icons/DubIcon.tsx new file mode 100644 index 0000000000..57d743c8eb --- /dev/null +++ b/docs/components/Icons/DubIcon.tsx @@ -0,0 +1,21 @@ +type Props = { + className?: string +} + +export function DubIcon({ className }: Props) { + return ( + + + + ) +} diff --git a/docs/components/Icons/T3Icon.tsx b/docs/components/Icons/T3Icon.tsx new file mode 100644 index 0000000000..e9b7e8f51e --- /dev/null +++ b/docs/components/Icons/T3Icon.tsx @@ -0,0 +1,35 @@ +type Props = { + className?: string +} + +export function T3Icon({ className }: Props) { + return ( + + + + + + + ) +} diff --git a/docs/components/Icons/VercelIcon.tsx b/docs/components/Icons/VercelIcon.tsx new file mode 100644 index 0000000000..a250d113ea --- /dev/null +++ b/docs/components/Icons/VercelIcon.tsx @@ -0,0 +1,18 @@ +type Props = { + className?: string +} + +export function VercelIcon({ className }: Props) { + return ( + + Vercel + + + ) +} diff --git a/docs/components/Providers/Marquee.tsx b/docs/components/Providers/Marquee.tsx new file mode 100644 index 0000000000..97496fa38f --- /dev/null +++ b/docs/components/Providers/Marquee.tsx @@ -0,0 +1,76 @@ +import React from "react" +import manifest from "@/data/manifest.json" + +const providersOAuth = manifest.providersOAuth +const providers = Object.keys(providersOAuth) + +const quarter = Math.ceil(providers.length / 4) +const row1 = providers.slice(0, quarter) +const row2 = providers.slice(quarter, quarter * 2) +const row3 = providers.slice(quarter * 2, quarter * 3) +const row4 = providers.slice(quarter * 3) + +const ProviderIcon = ({ name }) => ( +
+ {name} { + ;(e.currentTarget as HTMLImageElement).style.display = "none" + }} + /> +
+
+ {providersOAuth[name]} +
+
+
+
+) + +const ProviderMarquee = () => { + return ( +
+
+
+ {row1.map((name, i) => ( + + ))} + {row1.map((name, i) => ( + + ))} +
+ +
+ {row2.map((name, i) => ( + + ))} + {row2.map((name, i) => ( + + ))} +
+ +
+ {row3.map((name, i) => ( + + ))} + {row3.map((name, i) => ( + + ))} +
+ +
+ {row4.map((name, i) => ( + + ))} + {row4.map((name, i) => ( + + ))} +
+
+
+ ) +} + +export default ProviderMarquee diff --git a/docs/components/Providers/index.tsx b/docs/components/Providers/index.tsx new file mode 100644 index 0000000000..29c14223ef --- /dev/null +++ b/docs/components/Providers/index.tsx @@ -0,0 +1,19 @@ +import ProvidersMarquee from "./Marquee" + +export default function Providers() { + return ( +
+
+

+ Sign in with anything +

+
+ With over 100 popular providers, you can let your users sign in with + the services they already use and trust. +
+
+ + +
+ ) +} diff --git a/docs/components/RichTabs/index.tsx b/docs/components/RichTabs/index.tsx index 08fd79759e..f5756b121f 100644 --- a/docs/components/RichTabs/index.tsx +++ b/docs/components/RichTabs/index.tsx @@ -27,7 +27,7 @@ RichTabs.Trigger = function TabsTrigger({ +
+ +
+
+
+

+ Built by developers, for developers +

+
+ Auth.js is a community-driven project, backed by a transparent, + open-source philosophy. Your data is yours, and the code is open + to everyone. +
+
+ +
+
+

+ 25k+ +

+
+ GitHub Stars +
+
+ A testament to the community's trust and love for the project. +
+
+ +
+

+ 60M+ +

+
+ NPM Downloads +
+
+ Powering millions of applications every month, from side + projects to enterprise. +
+
+ +
+

+ 900+ +

+
+ Contributors +
+
+ A massive thank you to everyone who has contributed to the + project. +
+
+
+ + +
+
+ + ) +} diff --git a/docs/components/Testimonials/Card.tsx b/docs/components/Testimonials/Card.tsx new file mode 100644 index 0000000000..4b37d97c00 --- /dev/null +++ b/docs/components/Testimonials/Card.tsx @@ -0,0 +1,18 @@ +const TestimonialCard = ({ icon: Icon, title, children, iconClassName }) => { + return ( +
+
+ {/* The Icon component is rendered here with a standardized size */} + +
+
+

+ {title} +

+
{children}
+
+
+ ) +} + +export default TestimonialCard diff --git a/docs/components/Testimonials/index.tsx b/docs/components/Testimonials/index.tsx new file mode 100644 index 0000000000..1b90b3a018 --- /dev/null +++ b/docs/components/Testimonials/index.tsx @@ -0,0 +1,78 @@ +import React from "react" +import TestimonialCard from "./Card" + +import { VercelIcon } from "@/components/Icons/VercelIcon" +import { ChatGPTIcon } from "@/components/Icons/ChatGPTIcon" +import { CalIcon } from "@/components/Icons/CalIcon" +import { T3Icon } from "@/components/Icons/T3Icon" +import { ArtlistIcon } from "@/components/Icons/Artlist" +import { DubIcon } from "@/components/Icons/DubIcon" + +export default function Testimonials() { + return ( +
+
+
+

+ Trusted by the best in the game +

+
+ + The category-defining generative AI platform from OpenAI, enabling + developers to build intelligent applications. + + + + Open-source scheduling infrastructure for everyone, from + individuals to enterprise scale. + + + + Vercel provides the developer tools and cloud infrastructure to + build, scale, and secure a faster, more personalized web. + + + + An open-source link management tool for modern marketing teams to + create, share, and track short links. + + + + An opinionated, modular stack focused on simplicity, and type + safety, recommending Auth.js as its primary auth solution. + + + + A creative powerhouse providing creators with royalty-free music, + SFX, stock footage, and video editing software. + +
+
+
+
+ ) +} diff --git a/docs/pages/animated-stars.css b/docs/pages/animated-stars.css index 24eda72ace..5e2d89b65c 100644 --- a/docs/pages/animated-stars.css +++ b/docs/pages/animated-stars.css @@ -9,6 +9,7 @@ #stars { width: 1px; height: 1px; + border-radius: 50%; background: transparent; box-shadow: 117px 1613px #ce93d8, @@ -1427,6 +1428,7 @@ #stars2 { width: 2px; height: 2px; + border-radius: 50%; background: transparent; box-shadow: 1117px 1306px #ce93d8, @@ -1845,6 +1847,7 @@ #stars3 { width: 3px; height: 3px; + border-radius: 50%; background: transparent; box-shadow: 940px 1360px #ce93d8, @@ -2061,8 +2064,9 @@ } #stars4 { - width: 1px; - height: 1px; + width: 4px; + height: 4px; + border-radius: 50%; background: transparent; box-shadow: 233px 1976px #ce93d8, diff --git a/docs/pages/global.css b/docs/pages/global.css index 4de5a19375..7ac73ec623 100644 --- a/docs/pages/global.css +++ b/docs/pages/global.css @@ -289,3 +289,40 @@ html > head:has(meta[content*="reference/core/providers"]) + body .provider { @apply hidden; } } + +@keyframes scroll-left { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-50%); + } +} +.animate-scroll-left { + animation: scroll-left 15s linear infinite; +} + +@keyframes scroll-right { + 0% { + transform: translateX(-50%); + } + 100% { + transform: translateX(0); + } +} +.animate-scroll-right { + animation: scroll-right 15s linear infinite; +} + +@media (min-width: 1024px) { + .animate-scroll-left { + animation-duration: 75s; + } + .animate-scroll-right { + animation-duration: 75s; + } +} + +.filter-white { + filter: brightness(0) invert(1); +} diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index d06f6f31f3..87ec52e314 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -1,213 +1,29 @@ -import Link from "next/link" -import { Pre, Code } from "nextra/components" +import Hero from "@/components/Hero" +import Testimonials from "@/components/Testimonials" +import Advantages from "@/components/Advantages" +import Providers from "@/components/Providers" +import Stats from "@/components/Stats" +import CTA from "@/components/CTA" import Footer from "@/components/Footer" -import { RichTabs } from "@/components/RichTabs" -import { LogosMarquee } from "@/components/LogosMarquee" -import { Blur } from "@/components/Blur" -import { Guides } from "@/components/Guides" -import SvelteKit from "../public/img/etc/sveltekit.svg" -import Express from "../public/img/etc/express.svg" -import Next from "../public/img/etc/nextjs.svg" -import Qwik from "../public/img/etc/qwik.svg" - -import { CaretRight } from "@/icons"
-
-
-
- Auth.js -
-
Authentication for the Web.
-
Free and open source.
-
-
-
- - Get Started - - - - - - - - - Source - -
- -
- - -
- {[ - { value: "express", src: Express, name: "Express", darkInvert: true }, - { value: "nextjs", src: Next, name: "Next.js", darkInvert: true }, - { value: "qwik", src: Qwik, name: "Qwik", darkInvert: false }, - { value: "sveltekit", src: SvelteKit, name: "SvelteKit", darkInvert: false }, - ].map((trigger) => ( - - {`${trigger.name} - - ))} - - More - - -
-
-
-
-
-
-
-
- {Object.entries({ - nextjs: `\ -// auth.ts -import NextAuth from "next-auth" -import GitHub from "next-auth/providers/github" -export const { auth, handlers } = NextAuth({ providers: [GitHub] }) - -// middleware.ts -export { auth as middleware } from "@/auth" - -// app/api/auth/[...nextauth]/route.ts -import { handlers } from "@/auth" -export const { GET, POST } = handlers -`, - sveltekit: `\ -// src/auth.ts -import { SvelteKitAuth } from "@auth/sveltekit" -import GitHub from '@auth/sveltekit/providers/github' - -export const { handle } = SvelteKitAuth({ - providers: [GitHub], -}) + + + + + + +
-// src/hooks.server.ts -export { handle } from "./auth" -`, - express: `\ -// server.ts -import { express } from "express" -import { ExpressAuth } from "@auth/express" -import GitHub from "@auth/express/providers/github" - -const app = express() - -app.use("/auth/\*", ExpressAuth({ providers: [GitHub] })) -`, - qwik: `\ -// src/routes/plugin@auth.ts -import { QwikAuth } from "@auth/qwik" -import GitHub from "@auth/qwik/providers/github" -export const { onRequest, useSession } = QwikAuth$(() => ({ providers: [GitHub] })) -` -}).map(([key, code]) => - - -
-      
-        {code}
-      
-    
-
-)} -
-
+{/* Cool background effects (animated stars, gray radial gradient) */} -
- -
-
-
- Supports all these providers and more! -
-
- -
-