mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-07 20:37:44 +00:00
Og image generator and small fix (#4)
* feat: og and ui * fix: lines and border issue * fix: changelog ux * fix: better * fix: ui revamp * feat: og image and small fix * fix: docs and parsing
This commit is contained in:
committed by
GitHub
parent
d17f151dff
commit
2a576c8ff3
1
docs/README.md
Normal file
1
docs/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Better-auth docs site
|
||||||
345
docs/app/api/og/route.tsx
Normal file
345
docs/app/api/og/route.tsx
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
import { ImageResponse } from "@vercel/og";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Plus } from "lucide-react";
|
||||||
|
export const runtime = "edge";
|
||||||
|
const ogSchema = z.object({
|
||||||
|
heading: z.string(),
|
||||||
|
mode: z.string(),
|
||||||
|
type: z.string(),
|
||||||
|
});
|
||||||
|
// Use this example object to work with og image generator
|
||||||
|
|
||||||
|
// const ogData = {
|
||||||
|
// heading: "This is a test heading for the page",
|
||||||
|
// mode: "dark",
|
||||||
|
// type: "documentation",
|
||||||
|
// };
|
||||||
|
function GridPattern({
|
||||||
|
width = 40,
|
||||||
|
height = 40,
|
||||||
|
x = -1,
|
||||||
|
y = -1,
|
||||||
|
squares,
|
||||||
|
strokeDasharray = "1 1 1",
|
||||||
|
}: {
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
squares?: [number, number][];
|
||||||
|
strokeDasharray?: string;
|
||||||
|
}) {
|
||||||
|
const id = Math.random().toString(36).substr(2, 9);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
style={{
|
||||||
|
pointerEvents: "none",
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
fill: "rgba(107, 114, 128, 0.3)",
|
||||||
|
stroke: "rgba(107, 114, 128, 0.3)",
|
||||||
|
}}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<defs
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<pattern
|
||||||
|
id={id}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={`M.5 ${height}V.5H${width}`}
|
||||||
|
fill="none"
|
||||||
|
stroke="rgba(255,255,255,0.1)"
|
||||||
|
strokeDasharray={strokeDasharray}
|
||||||
|
/>
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<defs
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<pattern
|
||||||
|
id={id}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={`M.5 ${height}V.5H${width}`}
|
||||||
|
fill="none"
|
||||||
|
stroke="rgba(255,255,255,0.1)"
|
||||||
|
strokeDasharray={strokeDasharray}
|
||||||
|
/>
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect width="100%" height="100%" strokeWidth={0} fill={`url(#${id})`} />
|
||||||
|
{squares && (
|
||||||
|
<svg x={x} y={y}>
|
||||||
|
{squares.map(([squareX, squareY]) => (
|
||||||
|
<rect
|
||||||
|
key={`${squareX}-${squareY}`}
|
||||||
|
width={width - 1}
|
||||||
|
height={height - 1}
|
||||||
|
x={squareX * width + 1}
|
||||||
|
y={squareY * height + 1}
|
||||||
|
fill="rgba(255,255,255,0.05)"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(req: Request) {
|
||||||
|
try {
|
||||||
|
const geist = await fetch(
|
||||||
|
new URL("../../../assets/Geist.ttf", import.meta.url),
|
||||||
|
).then((res) => res.arrayBuffer());
|
||||||
|
const geistMono = await fetch(
|
||||||
|
new URL("../../../assets/GeistMono.ttf", import.meta.url),
|
||||||
|
).then((res) => res.arrayBuffer());
|
||||||
|
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const urlParamsValues = Object.fromEntries(url.searchParams);
|
||||||
|
// this is used with the above example
|
||||||
|
// const validParams = ogSchema.parse(ogData);
|
||||||
|
const validParams = ogSchema.parse(urlParamsValues);
|
||||||
|
console.log({ urlParamsValues });
|
||||||
|
console.log("THE VALUD PARAMS: ", { validParams });
|
||||||
|
const { heading, type, mode } = validParams;
|
||||||
|
const trueHeading =
|
||||||
|
heading.length > 140 ? `${heading.substring(0, 140)}...` : heading;
|
||||||
|
|
||||||
|
const paint = mode === "dark" ? "#fff" : "#000";
|
||||||
|
|
||||||
|
const fontSize = trueHeading.length > 100 ? "30px" : "60px";
|
||||||
|
return new ImageResponse(
|
||||||
|
(
|
||||||
|
<div
|
||||||
|
tw="flex w-full relative flex-col p-9"
|
||||||
|
style={{
|
||||||
|
color: paint,
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||||
|
boxShadow: "0 -20px 80px -20px rgba(134, 134, 240, 0.1) inset",
|
||||||
|
background: mode === "dark" ? "#1A0D0D" : "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
tw={`relative flex flex-col w-full h-full border-2 border-[${paint}]/20 p-8}`}
|
||||||
|
>
|
||||||
|
<GridPattern
|
||||||
|
width={40}
|
||||||
|
height={40}
|
||||||
|
squares={[
|
||||||
|
[1, 3],
|
||||||
|
[2, 1],
|
||||||
|
[5, 3],
|
||||||
|
[4, 1],
|
||||||
|
[-1, -1],
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "-9px",
|
||||||
|
right: "-9px",
|
||||||
|
}}
|
||||||
|
width="17"
|
||||||
|
height="17"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z"
|
||||||
|
fill="#ada8c4"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<svg
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "-9px",
|
||||||
|
left: "-9px",
|
||||||
|
}}
|
||||||
|
width="17"
|
||||||
|
height="17"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z"
|
||||||
|
fill="#ada8c4"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<svg
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "-9px",
|
||||||
|
left: "-9px",
|
||||||
|
}}
|
||||||
|
width="17"
|
||||||
|
height="17"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z"
|
||||||
|
fill="#ada8c4"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<svg
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "-9px",
|
||||||
|
right: "-9px",
|
||||||
|
}}
|
||||||
|
width="17"
|
||||||
|
height="17"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z"
|
||||||
|
fill="#ada8c4"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<svg
|
||||||
|
width="110"
|
||||||
|
height="110"
|
||||||
|
viewBox="0 0 200 200"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<rect width="200" height="200" fill="#D9D9D9" />
|
||||||
|
<line
|
||||||
|
x1="21.5"
|
||||||
|
y1="2.18557e-08"
|
||||||
|
x2="21.5"
|
||||||
|
y2="200"
|
||||||
|
stroke="#C4C4C4"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="173.5"
|
||||||
|
y1="2.18557e-08"
|
||||||
|
x2="173.5"
|
||||||
|
y2="200"
|
||||||
|
stroke="#C4C4C4"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="200"
|
||||||
|
y1="176.5"
|
||||||
|
x2="-4.37114e-08"
|
||||||
|
y2="176.5"
|
||||||
|
stroke="#C4C4C4"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="200"
|
||||||
|
y1="24.5"
|
||||||
|
x2="-4.37114e-08"
|
||||||
|
y2="24.5"
|
||||||
|
stroke="#C4C4C4"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M64.4545 135V65.1818H88.8636C93.7273 65.1818 97.7386 66.0227 100.898 67.7045C104.057 69.3636 106.409 71.6023 107.955 74.4205C109.5 77.2159 110.273 80.3182 110.273 83.7273C110.273 86.7273 109.739 89.2045 108.67 91.1591C107.625 93.1136 106.239 94.6591 104.511 95.7955C102.807 96.9318 100.955 97.7727 98.9545 98.3182V99C101.091 99.1364 103.239 99.8864 105.398 101.25C107.557 102.614 109.364 104.568 110.818 107.114C112.273 109.659 113 112.773 113 116.455C113 119.955 112.205 123.102 110.614 125.898C109.023 128.693 106.511 130.909 103.08 132.545C99.6477 134.182 95.1818 135 89.6818 135H64.4545ZM72.9091 127.5H89.6818C95.2045 127.5 99.125 126.432 101.443 124.295C103.784 122.136 104.955 119.523 104.955 116.455C104.955 114.091 104.352 111.909 103.148 109.909C101.943 107.886 100.227 106.273 98 105.068C95.7727 103.841 93.1364 103.227 90.0909 103.227H72.9091V127.5ZM72.9091 95.8636H88.5909C91.1364 95.8636 93.4318 95.3636 95.4773 94.3636C97.5455 93.3636 99.1818 91.9545 100.386 90.1364C101.614 88.3182 102.227 86.1818 102.227 83.7273C102.227 80.6591 101.159 78.0568 99.0227 75.9205C96.8864 73.7614 93.5 72.6818 88.8636 72.6818H72.9091V95.8636ZM131.665 135.545C129.983 135.545 128.54 134.943 127.335 133.739C126.131 132.534 125.528 131.091 125.528 129.409C125.528 127.727 126.131 126.284 127.335 125.08C128.54 123.875 129.983 123.273 131.665 123.273C133.347 123.273 134.79 123.875 135.994 125.08C137.199 126.284 137.801 127.727 137.801 129.409C137.801 130.523 137.517 131.545 136.949 132.477C136.403 133.409 135.665 134.159 134.733 134.727C133.824 135.273 132.801 135.545 131.665 135.545Z"
|
||||||
|
fill="#302208"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div tw="flex flex-col flex-1 py-10">
|
||||||
|
<div
|
||||||
|
style={{ fontFamily: "GeistMono", fontWeight: "normal" }}
|
||||||
|
tw="relative flex text-xl uppercase font-bold tracking-tight"
|
||||||
|
>
|
||||||
|
{type}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
tw="flex max-w-[70%] mt-5 tracking-tighter leading-[1.1] text-[30px] font-bold"
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginLeft: "-3px",
|
||||||
|
fontSize,
|
||||||
|
|
||||||
|
fontFamily: "GeistMono",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{trueHeading}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div tw="flex items-center w-full justify-between">
|
||||||
|
<div
|
||||||
|
tw="flex text-xl"
|
||||||
|
style={{ fontFamily: "GeistMono", fontWeight: "semibold" }}
|
||||||
|
>
|
||||||
|
Better Auth
|
||||||
|
</div>
|
||||||
|
<div tw="flex gap-2 items-center text-xl">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontFamily: "GeistMono",
|
||||||
|
}}
|
||||||
|
tw="flex ml-2"
|
||||||
|
>
|
||||||
|
<svg width="32" height="32" viewBox="0 0 48 48" fill="none">
|
||||||
|
<path
|
||||||
|
d="M30 44v-8a9.6 9.6 0 0 0-2-7c6 0 12-4 12-11 .16-2.5-.54-4.96-2-7 .56-2.3.56-4.7 0-7 0 0-2 0-6 3-5.28-1-10.72-1-16 0-4-3-6-3-6-3-.6 2.3-.6 4.7 0 7a10.806 10.806 0 0 0-2 7c0 7 6 11 12 11a9.43 9.43 0 0 0-1.7 3.3c-.34 1.2-.44 2.46-.3 3.7v8"
|
||||||
|
stroke={paint}
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M18 36c-9.02 4-10-4-14-4"
|
||||||
|
stroke={paint}
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
github.com/better-auth/better-auth
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
{
|
||||||
|
width: 1200,
|
||||||
|
height: 630,
|
||||||
|
fonts: [
|
||||||
|
{
|
||||||
|
name: "Geist",
|
||||||
|
data: geist,
|
||||||
|
weight: 400,
|
||||||
|
style: "normal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GeistMono",
|
||||||
|
data: geistMono,
|
||||||
|
weight: 700,
|
||||||
|
style: "normal",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.log({ err });
|
||||||
|
|
||||||
|
return new Response("Failed to generate the og image", { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,135 +6,135 @@ import { useId } from "react";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
function BookIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
function BookIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function GitHubIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
function GitHubIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function FeedIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
function FeedIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
fillRule="evenodd"
|
||||||
clipRule="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"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function XIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
function XIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Intro() {
|
export function Intro() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="">
|
<div className="">
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
{/* <Logo className="inline-block h-8 w-auto" /> */}
|
{/* <Logo className="inline-block h-8 w-auto" /> */}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="mt-14 font-sans font-semibold tracking-tighter text-5xl">
|
<h1 className="mt-14 font-sans font-semibold tracking-tighter text-5xl">
|
||||||
All of the changes made will be{" "}
|
All of the changes made will be{" "}
|
||||||
<span className="">available here.</span>
|
<span className="">available here.</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mt-4 text-sm text-gray-600 dark:text-gray-300">
|
<p className="mt-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
Better Auth is advanced authentication library for typescript packed by
|
Better Auth is advanced authentication library for typescript packed by
|
||||||
customizable and extendible plugin ecosystem
|
customizable and extendible plugin ecosystem
|
||||||
</p>
|
</p>
|
||||||
<hr className="h-px bg-gray-300 mt-5" />
|
<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">
|
<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
|
<IconLink
|
||||||
href="/docs"
|
href="/docs"
|
||||||
icon={BookIcon}
|
icon={BookIcon}
|
||||||
className="flex-none text-gray-600 dark:text-gray-300"
|
className="flex-none text-gray-600 dark:text-gray-300"
|
||||||
>
|
>
|
||||||
Documentation
|
Documentation
|
||||||
</IconLink>
|
</IconLink>
|
||||||
<IconLink
|
<IconLink
|
||||||
href="https://github.com/better-auth/better-auth"
|
href="https://github.com/better-auth/better-auth"
|
||||||
icon={GitHubIcon}
|
icon={GitHubIcon}
|
||||||
className="flex-none text-gray-600 dark:text-gray-300"
|
className="flex-none text-gray-600 dark:text-gray-300"
|
||||||
>
|
>
|
||||||
GitHub
|
GitHub
|
||||||
</IconLink>
|
</IconLink>
|
||||||
<IconLink
|
<IconLink
|
||||||
href="/feed.xml"
|
href="/feed.xml"
|
||||||
icon={FeedIcon}
|
icon={FeedIcon}
|
||||||
className="flex-none text-gray-600 dark:text-gray-300"
|
className="flex-none text-gray-600 dark:text-gray-300"
|
||||||
>
|
>
|
||||||
RSS
|
RSS
|
||||||
</IconLink>
|
</IconLink>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function IntroFooter() {
|
export function IntroFooter() {
|
||||||
return (
|
return (
|
||||||
<p className="flex items-baseline gap-x-2 text-[0.8125rem]/6 text-gray-500">
|
<p className="flex items-baseline gap-x-2 text-[0.8125rem]/6 text-gray-500">
|
||||||
Brought to you by{" "}
|
Brought to you by{" "}
|
||||||
<IconLink href="#" icon={XIcon} compact>
|
<IconLink href="#" icon={XIcon} compact>
|
||||||
BETTER-AUTH.
|
BETTER-AUTH.
|
||||||
</IconLink>
|
</IconLink>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SignUpForm() {
|
export function SignUpForm() {
|
||||||
let id = useId();
|
let id = useId();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="relative isolate mt-8 flex items-center pr-1">
|
<form className="relative isolate mt-8 flex items-center pr-1">
|
||||||
<label htmlFor={id} className="sr-only">
|
<label htmlFor={id} className="sr-only">
|
||||||
Email address
|
Email address
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="absolute inset-0 -z-10 rounded-lg transition peer-focus:ring-4 peer-focus:ring-sky-300/15" />
|
<div className="absolute inset-0 -z-10 rounded-lg transition peer-focus:ring-4 peer-focus:ring-sky-300/15" />
|
||||||
<div className="absolute inset-0 -z-10 rounded-lg bg-white/2.5 ring-1 ring-white/15 transition peer-focus:ring-sky-300" />
|
<div className="absolute inset-0 -z-10 rounded-lg bg-white/2.5 ring-1 ring-white/15 transition peer-focus:ring-sky-300" />
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function IconLink({
|
export function IconLink({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
compact = false,
|
compact = false,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentPropsWithoutRef<typeof Link> & {
|
}: React.ComponentPropsWithoutRef<typeof Link> & {
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
icon?: React.ComponentType<{ className?: string }>;
|
icon?: React.ComponentType<{ className?: string }>;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
{...props}
|
{...props}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
"group relative isolate flex items-center rounded-lg px-2 py-0.5 text-[0.8125rem]/6 font-medium text-black/70 dark:text-white/30 transition-colors hover:text-stone-300",
|
"group relative isolate flex items-center rounded-lg px-2 py-0.5 text-[0.8125rem]/6 font-medium text-black/70 dark:text-white/30 transition-colors hover:text-stone-300",
|
||||||
compact ? "gap-x-2" : "gap-x-3",
|
compact ? "gap-x-2" : "gap-x-3",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="absolute inset-0 -z-10 scale-75 rounded-lg bg-white/5 opacity-0 transition group-hover:scale-100 group-hover:opacity-100" />
|
<span className="absolute inset-0 -z-10 scale-75 rounded-lg bg-white/5 opacity-0 transition group-hover:scale-100 group-hover:opacity-100" />
|
||||||
{Icon && <Icon className="h-4 w-4 flex-none" />}
|
{Icon && <Icon className="h-4 w-4 flex-none" />}
|
||||||
<span className="self-baseline text-black/70 dark:text-white">
|
<span className="self-baseline text-black/70 dark:text-white">
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
39
docs/app/changelogs/_logs/2024-08-09.tsx
Normal file
39
docs/app/changelogs/_logs/2024-08-09.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
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] object-cover rounded-lg" />
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<h2 className="text-2xl font-bold tracking-tighter">
|
||||||
|
Commit message suggestions
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 dark: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>
|
||||||
|
</div>
|
||||||
|
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
|
||||||
|
<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
|
||||||
@@ -2,24 +2,24 @@ import { AnimatePresence } from "@/components/ui/fade-in";
|
|||||||
import { Logs } from "./_logs";
|
import { Logs } from "./_logs";
|
||||||
import { FormattedDate } from "./_components/fmt-dates";
|
import { FormattedDate } from "./_components/fmt-dates";
|
||||||
const ChangelogPage = () => {
|
const ChangelogPage = () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="mt-10 overflow-visible h-full flex flex-col gap-10">
|
<div className="mt-10 overflow-visible h-full flex flex-col gap-10">
|
||||||
{Logs.map((log) => {
|
{Logs.map((log) => {
|
||||||
return (
|
return (
|
||||||
<div className="relative my-5 h-auto">
|
<div className="relative my-5 h-auto">
|
||||||
<div className="sticky top-2 flex-1 h-full">
|
<div className="sticky top-2 flex-1 h-full">
|
||||||
<FormattedDate
|
<FormattedDate
|
||||||
className="absolute md:-left-32 left-0 text-sm -top-8 md:top-0 font-light"
|
className="absolute md:-left-32 left-0 text-sm -top-8 md:top-0 font-light"
|
||||||
date={log.date}
|
date={log.date}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<log.component />
|
<log.component />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ChangelogPage;
|
export default ChangelogPage;
|
||||||
|
|||||||
@@ -2,58 +2,84 @@ import { getPage, getPages } from "@/app/source";
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { DocsPage, DocsBody, DocsTitle } from "fumadocs-ui/page";
|
import { DocsPage, DocsBody, DocsTitle } from "fumadocs-ui/page";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
import { absoluteUrl } from "@/lib/utils";
|
||||||
|
|
||||||
export default async function Page({
|
export default async function Page({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: { slug?: string[] };
|
params: { slug?: string[] };
|
||||||
}) {
|
}) {
|
||||||
const page = getPage(params.slug);
|
const page = getPage(params.slug);
|
||||||
|
|
||||||
if (page == null) {
|
if (page == null) {
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
const MDX = page.data.exports.default;
|
||||||
|
|
||||||
const MDX = page.data.exports.default;
|
return (
|
||||||
|
<DocsPage
|
||||||
return (
|
toc={page.data.exports.toc}
|
||||||
<DocsPage
|
full={page.data.full}
|
||||||
toc={page.data.exports.toc}
|
editOnGithub={{
|
||||||
full={page.data.full}
|
owner: "better-auth",
|
||||||
editOnGithub={{
|
repo: "better-auth",
|
||||||
owner: "better-auth",
|
path: "/docs/content/docs",
|
||||||
repo: "better-auth",
|
}}
|
||||||
path: "/docs/content/docs",
|
tableOfContent={{
|
||||||
}}
|
style: "clerk",
|
||||||
tableOfContent={{
|
header: <div className="h-4 w-10"></div>,
|
||||||
style: "clerk",
|
}}
|
||||||
header: <div className="h-4 w-10"></div>,
|
footer={{
|
||||||
}}
|
enabled: false,
|
||||||
footer={{
|
}}
|
||||||
enabled: false,
|
>
|
||||||
}}
|
<DocsTitle>{page.data.title}</DocsTitle>
|
||||||
>
|
<DocsBody>
|
||||||
<DocsTitle>{page.data.title}</DocsTitle>
|
<MDX />
|
||||||
<DocsBody>
|
</DocsBody>
|
||||||
<MDX />
|
</DocsPage>
|
||||||
</DocsBody>
|
);
|
||||||
</DocsPage>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
return getPages().map((page) => ({
|
return getPages().map((page) => ({
|
||||||
slug: page.slugs,
|
slug: page.slugs,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
|
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
|
||||||
const page = getPage(params.slug);
|
const page = getPage(params.slug);
|
||||||
|
if (page == null) notFound();
|
||||||
|
const baseUrl = process.env.NEXT_APP_PUBLIC_URL;
|
||||||
|
const url = new URL(`${baseUrl}/api/og`);
|
||||||
|
const { title, description } = page.data;
|
||||||
|
const pageSlug = page.file.path;
|
||||||
|
url.searchParams.set("type", "Documentation");
|
||||||
|
url.searchParams.set("mode", "dark");
|
||||||
|
url.searchParams.set("heading", `${title}`);
|
||||||
|
|
||||||
if (page == null) notFound();
|
return {
|
||||||
|
title,
|
||||||
return {
|
description,
|
||||||
title: page.data.title,
|
openGraph: {
|
||||||
description: page.data.description,
|
title,
|
||||||
} satisfies Metadata;
|
description,
|
||||||
|
type: "Documentation",
|
||||||
|
url: absoluteUrl(`docs/${pageSlug}`),
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: url.toString(),
|
||||||
|
width: 1200,
|
||||||
|
height: 630,
|
||||||
|
alt: title,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary_large_image",
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
images: [url.toString()],
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
|||||||
Github.
|
Github.
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
</Banner>
|
</Banner>
|
||||||
|
<body className={`${GeistSans.variable} ${GeistMono.variable} font-sans overflow-x-hidden`}>
|
||||||
<RootProvider>
|
<RootProvider>
|
||||||
<NavbarProvider>
|
<NavbarProvider>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ import Section from "@/components/landing/section";
|
|||||||
import Hero from "@/components/landing/hero";
|
import Hero from "@/components/landing/hero";
|
||||||
import Features from "@/components/features";
|
import Features from "@/components/features";
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return (
|
return (
|
||||||
<main className="h-min mx-auto ">
|
<main className="h-min mx-auto ">
|
||||||
<Section
|
<Section
|
||||||
className="-z-1 mb-1 overflow-y-clip"
|
className="-z-1 mb-1 overflow-y-clip"
|
||||||
crosses
|
crosses
|
||||||
crossesOffset="lg:translate-y-[5.25rem]"
|
crossesOffset="lg:translate-y-[5.25rem]"
|
||||||
customPaddings
|
customPaddings
|
||||||
id="hero"
|
id="hero"
|
||||||
>
|
>
|
||||||
<Hero />
|
<Hero />
|
||||||
<Features />
|
<Features />
|
||||||
<hr className="h-px bg-gray-200" />
|
<hr className="h-px bg-gray-200" />
|
||||||
</Section>
|
</Section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
10
docs/app/robots.ts
Normal file
10
docs/app/robots.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
export default function robots(): MetadataRoute.Robots {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
userAgent: "*",
|
||||||
|
allow: "/",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
BIN
docs/assets/Geist.ttf
Normal file
BIN
docs/assets/Geist.ttf
Normal file
Binary file not shown.
BIN
docs/assets/GeistMono.ttf
Normal file
BIN
docs/assets/GeistMono.ttf
Normal file
Binary file not shown.
@@ -19,9 +19,9 @@
|
|||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta::before {
|
.beta::before {
|
||||||
content: " ";
|
content: " ";
|
||||||
width: 1.5625rem;
|
width: 1.5625rem;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
@@ -31,10 +31,12 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
transition: background 0.3s linear, width 0.3s linear;
|
transition:
|
||||||
}
|
background 0.3s linear,
|
||||||
|
width 0.3s linear;
|
||||||
|
}
|
||||||
|
|
||||||
.beta .text {
|
.beta .text {
|
||||||
font-size: 1.125em;
|
font-size: 1.125em;
|
||||||
line-height: 1.33333em;
|
line-height: 1.33333em;
|
||||||
padding-left: 2em;
|
padding-left: 2em;
|
||||||
@@ -44,70 +46,74 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta .top_key {
|
.beta .top_key {
|
||||||
height: 2px;
|
height: 2px;
|
||||||
width: 1.5625rem;
|
width: 1.5625rem;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
left: 0.625rem;
|
left: 0.625rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #0c0a09;
|
background: #0c0a09;
|
||||||
transition: width 0.5s ease-out, left 0.3s ease-out;
|
transition:
|
||||||
}
|
width 0.5s ease-out,
|
||||||
|
left 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
.beta .bottom_key_1 {
|
.beta .bottom_key_1 {
|
||||||
height: 2px;
|
height: 2px;
|
||||||
width: 1.5625rem;
|
width: 1.5625rem;
|
||||||
right: 1.875rem;
|
right: 1.875rem;
|
||||||
bottom: -2px;
|
bottom: -2px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #0c0a09;
|
background: #0c0a09;
|
||||||
transition: width 0.5s ease-out, right 0.3s ease-out;
|
transition:
|
||||||
}
|
width 0.5s ease-out,
|
||||||
|
right 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
.beta .bottom_key_2 {
|
.beta .bottom_key_2 {
|
||||||
height: 2px;
|
height: 2px;
|
||||||
width: 0.625rem;
|
width: 0.625rem;
|
||||||
right: 0.625rem;
|
right: 0.625rem;
|
||||||
bottom: -2px;
|
bottom: -2px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #0c0a09;
|
background: #0c0a09;
|
||||||
transition: width 0.5s ease-out, right 0.3s ease-out;
|
transition:
|
||||||
}
|
width 0.5s ease-out,
|
||||||
|
right 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
.beta {
|
.beta {
|
||||||
color: white;
|
color: white;
|
||||||
background: rgb(247, 247, 255);
|
background: rgb(247, 247, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta:hover {
|
.beta:hover {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta:hover .text {
|
.beta:hover .text {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta::before {
|
.beta::before {
|
||||||
width: 0.9375rem;
|
width: 0.9375rem;
|
||||||
background: rgb(39, 37, 42);
|
background: rgb(39, 37, 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta .text {
|
.beta .text {
|
||||||
color: black;
|
color: black;
|
||||||
padding-left: 1.5em;
|
padding-left: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.beta:hover .top_key {
|
||||||
|
|
||||||
.beta:hover .top_key {
|
|
||||||
left: -2px;
|
left: -2px;
|
||||||
width: 0px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beta:hover .bottom_key_1,
|
.beta:hover .bottom_key_1,
|
||||||
.beta:hover .bottom_key_2 {
|
.beta:hover .bottom_key_2 {
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import badgestyle from "./badge.module.css";
|
import badgestyle from "./badge.module.css";
|
||||||
export const PulicBetaBadge = ({ text }: { text?: string }) => {
|
export const PulicBetaBadge = ({ text }: { text?: string }) => {
|
||||||
return (
|
return (
|
||||||
<div className={badgestyle.beta}>
|
<div className={badgestyle.beta}>
|
||||||
<span className={badgestyle.top_key}></span>
|
<span className={badgestyle.top_key}></span>
|
||||||
<span className={badgestyle.text}>{text || "BETA"}</span>
|
<span className={badgestyle.text}>{text || "BETA"}</span>
|
||||||
<span className={badgestyle.bottom_key_1}></span>
|
<span className={badgestyle.bottom_key_1}></span>
|
||||||
<span className={badgestyle.bottom_key_2}></span>
|
<span className={badgestyle.bottom_key_2}></span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { techStackIcons } from "./techstack-icons";
|
import { techStackIcons } from "./techstack-icons";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
|
|
||||||
export const TechStackDisplay = ({
|
export const TechStackDisplay = ({
|
||||||
skills,
|
skills,
|
||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
skills: string[];
|
skills: string[];
|
||||||
className?: string;
|
className?: string;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex gap-7 flex-wrap mt-3 justify-center items-center max-w-4xl",
|
"flex gap-7 flex-wrap mt-3 justify-center items-center max-w-4xl",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{skills.map((icon) => {
|
{skills.map((icon) => {
|
||||||
return (
|
return (
|
||||||
<TooltipProvider key={icon}>
|
<TooltipProvider key={icon}>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<span className="transform duration-300 hover:rotate-12 transition-transform">
|
<span className="transform duration-300 hover:rotate-12 transition-transform">
|
||||||
{techStackIcons[icon].icon}
|
{techStackIcons[icon].icon}
|
||||||
</span>
|
</span>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent className="text-white/80 bg-gradient-to-tr from-black/80 via-black to-black/90 z-1">
|
<TooltipContent className="text-white/80 bg-gradient-to-tr from-black/80 via-black to-black/90 z-1">
|
||||||
{techStackIcons[icon].name}
|
{techStackIcons[icon].name}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
Globe2Icon,
|
Globe2Icon,
|
||||||
PlugIcon,
|
PlugIcon,
|
||||||
PlugZap2Icon,
|
PlugZap2Icon,
|
||||||
Plus,
|
Plus,
|
||||||
RabbitIcon,
|
RabbitIcon,
|
||||||
ShieldCheckIcon,
|
ShieldCheckIcon,
|
||||||
Webhook,
|
Webhook,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { LockClosedIcon } from "@radix-ui/react-icons";
|
import { LockClosedIcon } from "@radix-ui/react-icons";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -18,193 +18,193 @@ import { TechStackDisplay } from "./display-techstack";
|
|||||||
import { Ripple } from "./ripple";
|
import { Ripple } from "./ripple";
|
||||||
|
|
||||||
export default function Features() {
|
export default function Features() {
|
||||||
return (
|
return (
|
||||||
<div className="md:w-10/12 overflow-x-hidden mt-10 mx-auto font-geist relative md:border-l-0 md:border-[1.2px] rounded-none -pr-2">
|
<div className="md:w-10/12 overflow-x-hidden mt-10 mx-auto font-geist relative md:border-l-0 md:border-[1.2px] rounded-none -pr-2">
|
||||||
<Plus className="absolute top-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
<Plus className="absolute top-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 md:mx-0 grid-rows-4 md:grid-rows-4 w-full">
|
<div className="grid grid-cols-1 md:grid-cols-3 md:mx-0 grid-rows-4 md:grid-rows-4 w-full">
|
||||||
<div className="relative items-start justify-start border-l-[1.2px] border-t-[1.2px] md:border-t-0 transform-gpu flex flex-col p-10 overflow-clip">
|
<div className="relative items-start justify-start border-l-[1.2px] border-t-[1.2px] md:border-t-0 transform-gpu flex flex-col p-10 overflow-clip">
|
||||||
<Plus className="absolute bottom-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
<Plus className="absolute bottom-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
||||||
|
|
||||||
<div className="flex gap-2 items-center my-1">
|
<div className="flex gap-2 items-center my-1">
|
||||||
<PlugZap2Icon className="w-4 h-4" />
|
<PlugZap2Icon className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
Framework Agnostic{" "}
|
Framework Agnostic{" "}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<div className="max-w-full">
|
<div className="max-w-full">
|
||||||
<div className="flex gap-3 ">
|
<div className="flex gap-3 ">
|
||||||
<p className="text-xl md:text-2xl tracking-tighter font-normal max-w-lg">
|
<p className="text-xl md:text-2xl tracking-tighter font-normal max-w-lg">
|
||||||
Supports popular <strong>frameworks</strong>
|
Supports popular <strong>frameworks</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-left text-sm mt-2 text-muted-foreground">
|
<p className="text-left text-sm mt-2 text-muted-foreground">
|
||||||
Supports your favorite frontend, backend and meta frameworks,
|
Supports your favorite frontend, backend and meta frameworks,
|
||||||
including React, Vue, Svelte, Astro, Solid, Next.js, Nuxt.js,
|
including React, Vue, Svelte, Astro, Solid, Next.js, Nuxt.js,
|
||||||
Hono, and more{" "}
|
Hono, and more{" "}
|
||||||
<a className="text-gray-50" href="/docs" target="_blank">
|
<a className="text-gray-50" href="/docs" target="_blank">
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative items-start justify-start border-l-[1.2px] border-t-[1.2px] md:border-t-0 transform-gpu flex flex-col p-10">
|
<div className="relative items-start justify-start border-l-[1.2px] border-t-[1.2px] md:border-t-0 transform-gpu flex flex-col p-10">
|
||||||
<Plus className="absolute bottom-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
<Plus className="absolute bottom-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
||||||
|
|
||||||
<div className="flex gap-2 items-center my-1">
|
<div className="flex gap-2 items-center my-1">
|
||||||
<LockClosedIcon className="w-4 h-4" />
|
<LockClosedIcon className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">Authentication</p>
|
<p className="text-gray-600 dark:text-gray-400">Authentication</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<div className="max-w-full">
|
<div className="max-w-full">
|
||||||
<div className="flex gap-3 ">
|
<div className="flex gap-3 ">
|
||||||
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
||||||
Email & Password <strong>Authentication</strong>
|
Email & Password <strong>Authentication</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-left text-sm mt-2 text-muted-foreground">
|
<p className="text-left text-sm mt-2 text-muted-foreground">
|
||||||
Builtin support for email and password authentication, with secure
|
Builtin support for email and password authentication, with secure
|
||||||
password hashing and account management features{" "}
|
password hashing and account management features{" "}
|
||||||
<a className="text-gray-50" href="/docs" target="_blank">
|
<a className="text-gray-50" href="/docs" target="_blank">
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative items-start justify-start md:border-l-[0.2px] border-t-[1.2px] md:border-t-0 flex flex-col p-10">
|
<div className="relative items-start justify-start md:border-l-[0.2px] border-t-[1.2px] md:border-t-0 flex flex-col p-10">
|
||||||
<Plus className="absolute bottom-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
<Plus className="absolute bottom-[-17px] left-[-17px] text-black/20 dark:text-white/30 w-8 h-8" />
|
||||||
|
|
||||||
<div className="flex gap-2 items-center my-1">
|
<div className="flex gap-2 items-center my-1">
|
||||||
<Webhook className="w-4 h-4" />
|
<Webhook className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">Social Sign-on</p>
|
<p className="text-gray-600 dark:text-gray-400">Social Sign-on</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<div className="max-w-full">
|
<div className="max-w-full">
|
||||||
<div className="flex gap-3 ">
|
<div className="flex gap-3 ">
|
||||||
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
||||||
Support multiple <strong>OAuth providers.</strong>
|
Support multiple <strong>OAuth providers.</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-left text-sm mt-2 text-muted-foreground">
|
<p className="text-left text-sm mt-2 text-muted-foreground">
|
||||||
Allow users to sign in with their accounts, including Github,
|
Allow users to sign in with their accounts, including Github,
|
||||||
Google, Discord, Twitter, and more.{" "}
|
Google, Discord, Twitter, and more.{" "}
|
||||||
<a className="text-gray-50" href="#" target="_blank">
|
<a className="text-gray-50" href="#" target="_blank">
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="items-start justify-start border-l-[1.2px] border-t-[1.2px] flex flex-col p-10 ">
|
<div className="items-start justify-start border-l-[1.2px] border-t-[1.2px] flex flex-col p-10 ">
|
||||||
<div className="flex gap-2 items-center my-1">
|
<div className="flex gap-2 items-center my-1">
|
||||||
<ShieldCheckIcon className="w-4 h-4" />
|
<ShieldCheckIcon className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">Two Factor</p>
|
<p className="text-gray-600 dark:text-gray-400">Two Factor</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<div className="max-w-full">
|
<div className="max-w-full">
|
||||||
<div className="flex gap-3 ">
|
<div className="flex gap-3 ">
|
||||||
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
||||||
Two Factor <strong>Authentication</strong>
|
Two Factor <strong>Authentication</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-left text-sm mt-2 text-muted-foreground">
|
<p className="text-left text-sm mt-2 text-muted-foreground">
|
||||||
With our built-in two factor authentication plugin, you can add an
|
With our built-in two factor authentication plugin, you can add an
|
||||||
extra layer of security to your account.{" "}
|
extra layer of security to your account.{" "}
|
||||||
<Link className="text-gray-50" href="/docs" target="_blank">
|
<Link className="text-gray-50" href="/docs" target="_blank">
|
||||||
Learn more
|
Learn more
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="items-start justify-staart border-l-[1.2px] border-t-[1.2px] flex flex-col p-10 ">
|
<div className="items-start justify-staart border-l-[1.2px] border-t-[1.2px] flex flex-col p-10 ">
|
||||||
<div className="flex gap-2 items-center my-1">
|
<div className="flex gap-2 items-center my-1">
|
||||||
<RabbitIcon className="w-4 h-4" />
|
<RabbitIcon className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
Organization & Access Control{" "}
|
Organization & Access Control{" "}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<div className="max-w-full">
|
<div className="max-w-full">
|
||||||
<div className="flex gap-3 ">
|
<div className="flex gap-3 ">
|
||||||
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
||||||
Gain and manage <strong>access.</strong>
|
Gain and manage <strong>access.</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-left text-sm mt-2 text-muted-foreground">
|
<p className="text-left text-sm mt-2 text-muted-foreground">
|
||||||
Manage users and their access to resources within your
|
Manage users and their access to resources within your
|
||||||
application.{" "}
|
application.{" "}
|
||||||
<a className="text-gray-50" href="/docs" target="_blank">
|
<a className="text-gray-50" href="/docs" target="_blank">
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="items-start justify-start border-l-[1.2px] border-t-[1.2px] transform-gpu relative flex flex-col p-10 ">
|
<div className="items-start justify-start border-l-[1.2px] border-t-[1.2px] transform-gpu relative flex flex-col p-10 ">
|
||||||
<Plus className="absolute bottom-[-15px] right-[-15px] text-black/20 dark:text-white/40 w-8 h-8" />
|
<Plus className="absolute bottom-[-15px] right-[-15px] text-black/20 dark:text-white/40 w-8 h-8" />
|
||||||
<div className="flex gap-2 items-center my-1">
|
<div className="flex gap-2 items-center my-1">
|
||||||
<PlugIcon className="w-4 h-4" />
|
<PlugIcon className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
Plugin Ecosystem{" "}
|
Plugin Ecosystem{" "}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="max-w-full">
|
<div className="max-w-full">
|
||||||
<div className="flex gap-3 ">
|
<div className="flex gap-3 ">
|
||||||
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
<p className="text-2xl tracking-tighter font-normal max-w-lg">
|
||||||
Pluggable with <strong>custom.</strong>
|
Pluggable with <strong>custom.</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<p className="text-left text-sm mt-2 text-muted-foreground">
|
<p className="text-left text-sm mt-2 text-muted-foreground">
|
||||||
Enhance your application with our official plugins and those
|
Enhance your application with our official plugins and those
|
||||||
created by the community.{" "}
|
created by the community.{" "}
|
||||||
<a className="text-gray-50" href="/docs" target="_blank">
|
<a className="text-gray-50" href="/docs" target="_blank">
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative md:grid md:col-span-3 grid-cols-2 row-span-2 border-t-[1.2px] border-l-[1.2px] md:border-b-[1.2px] dark:border-b-0 h-full py-20 ">
|
<div className="relative md:grid md:col-span-3 grid-cols-2 row-span-2 border-t-[1.2px] border-l-[1.2px] md:border-b-[1.2px] dark:border-b-0 h-full py-20 ">
|
||||||
<Plus className="absolute top-[-15px] left-[-15px] text-black/20 dark:text-black/20 w-8 h-8 " />
|
<Plus className="absolute top-[-15px] left-[-15px] text-black/20 dark:text-black/20 w-8 h-8 " />
|
||||||
<Plus className="absolute top-[-15px] right-[-15px] text-black/20 dark:text-black/20 w-8 h-8 " />
|
<Plus className="absolute top-[-15px] right-[-15px] text-black/20 dark:text-black/20 w-8 h-8 " />
|
||||||
<div className="p-16 pt-10 md:px-10 h-full md:absolute top-0 left-0 w-full">
|
<div className="p-16 pt-10 md:px-10 h-full md:absolute top-0 left-0 w-full">
|
||||||
<div className="flex flex-col gap-3 justify-center h-full items-center w-full">
|
<div className="flex flex-col gap-3 justify-center h-full items-center w-full">
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-2 items-center">
|
||||||
<Globe2Icon className="w-4 h-4" />
|
<Globe2Icon className="w-4 h-4" />
|
||||||
<p className="text-gray-600 dark:text-gray-400">
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
Own your auth
|
Own your auth
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-4xl md:text-4xl mt-4 tracking-tighter font-normal max-w-md mx-auto text-center">
|
<p className="text-4xl md:text-4xl mt-4 tracking-tighter font-normal max-w-md mx-auto text-center">
|
||||||
<strong>Roll your own auth with confidence in minutes!</strong>
|
<strong>Roll your own auth with confidence in minutes!</strong>
|
||||||
</p>
|
</p>
|
||||||
<div className="flex mt-[10px] z-20 justify-center items-start">
|
<div className="flex mt-[10px] z-20 justify-center items-start">
|
||||||
<TechStackDisplay
|
<TechStackDisplay
|
||||||
skills={[
|
skills={[
|
||||||
"nextJs",
|
"nextJs",
|
||||||
"nuxt",
|
"nuxt",
|
||||||
"svelteKit",
|
"svelteKit",
|
||||||
"astro",
|
"astro",
|
||||||
"solidStart",
|
"solidStart",
|
||||||
"react",
|
"react",
|
||||||
"hono",
|
"hono",
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/docs" className="z-50">
|
<Link href="/docs" className="z-50">
|
||||||
<Button className="mt-4 rounded-none p-5 ml-auto">
|
<Button className="mt-4 rounded-none p-5 ml-auto">
|
||||||
Start now!
|
Start now!
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<Ripple />
|
<Ripple />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ export default function Hero() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [activeTab, setActiveTab] = useState("auth.ts");
|
const [activeTab, setActiveTab] = useState("auth.ts");
|
||||||
const code = tabs.find((tab) => tab.name === activeTab)?.code ?? "";
|
const code = tabs.find((tab) => tab.name === activeTab)?.code ?? "";
|
||||||
93;
|
|
||||||
return (
|
return (
|
||||||
<section className="w-full mx-auto px-10 flex min-h-[85vh] py-16 items-center justify-center gap-20">
|
<section className="w-full mx-auto px-10 flex min-h-[85vh] py-16 items-center justify-center gap-20">
|
||||||
<div className="overflow-hidden bg-transparent dark:-mb-32 dark:mt-[-4.75rem] dark:pb-32 dark:pt-[4.75rem] md:px-10">
|
<div className="overflow-hidden bg-transparent dark:-mb-32 dark:mt-[-4.75rem] dark:pb-32 dark:pt-[4.75rem] md:px-10">
|
||||||
@@ -99,14 +98,14 @@ export default function Hero() {
|
|||||||
<div className="relative z-10 md:text-center lg:text-left">
|
<div className="relative z-10 md:text-center lg:text-left">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="flex flex-col items-start gap-2">
|
<div className="flex flex-col items-start gap-2">
|
||||||
<div className="flex items-center gap-2 relative">
|
<PulicBetaBadge text="Public Beta" />
|
||||||
|
<div className="flex mt-2 items-center gap-2 relative">
|
||||||
<Cover>
|
<Cover>
|
||||||
<p className="inline dark:text-white opacity-90 2xl md:text-3xl lg:text-5xl tracking-tight relative">
|
<p className="inline dark:text-white opacity-90 2xl md:text-3xl lg:text-5xl tracking-tight relative">
|
||||||
Better Auth.
|
Better Auth.
|
||||||
</p>
|
</p>
|
||||||
</Cover>
|
</Cover>
|
||||||
</div>
|
</div>
|
||||||
<PulicBetaBadge text="Public Beta" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="mt-3 md:text-2xl tracking-tight dark:text-zinc-300 text-zinc-800">
|
<p className="mt-3 md:text-2xl tracking-tight dark:text-zinc-300 text-zinc-800">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
const SectionSvg = ({
|
const SectionSvg = ({
|
||||||
crossesOffset,
|
crossesOffset,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
@@ -2,45 +2,45 @@ import type React from "react";
|
|||||||
import SectionSvg from "./section-svg";
|
import SectionSvg from "./section-svg";
|
||||||
|
|
||||||
const Section = ({
|
const Section = ({
|
||||||
className,
|
className,
|
||||||
id,
|
id,
|
||||||
crosses,
|
crosses,
|
||||||
crossesOffset,
|
crossesOffset,
|
||||||
customPaddings,
|
customPaddings,
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
className: string;
|
className: string;
|
||||||
id: string;
|
id: string;
|
||||||
crosses?: boolean;
|
crosses?: boolean;
|
||||||
crossesOffset: string;
|
crossesOffset: string;
|
||||||
customPaddings: boolean;
|
customPaddings: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={id}
|
id={id}
|
||||||
className={`
|
className={`
|
||||||
relative
|
relative
|
||||||
${customPaddings || `py-10 lg:py-16 ${crosses ? "" : ""}`}
|
${customPaddings || `py-10 lg:py-16 ${crosses ? "" : ""}`}
|
||||||
${className || " "}`}
|
${className || " "}`}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
<div className="hidden absolute top-0 left-5 w-[0.0625rem] h-[calc(100%_+_30px)] dark:bg-[#26242C] bg-stone-200 pointer-events-none md:block lg:left-7.5 xl:left-16" />
|
<div className="hidden absolute top-0 left-5 w-[0.0625rem] h-[calc(100%_+_30px)] dark:bg-[#26242C] bg-stone-200 pointer-events-none md:block lg:left-7.5 xl:left-16" />
|
||||||
<div className="hidden absolute top-0 right-5 w-[0.0625rem] h-[calc(100%_+_30px)] dark:bg-[#26242C] bg-stone-200 pointer-events-none md:block lg:right-7.5 xl:right-14" />
|
<div className="hidden absolute top-0 right-5 w-[0.0625rem] h-[calc(100%_+_30px)] dark:bg-[#26242C] bg-stone-200 pointer-events-none md:block lg:right-7.5 xl:right-14" />
|
||||||
|
|
||||||
{crosses && (
|
{crosses && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`hidden absolute top-0 left-7.5 right-7.5 h-0.25 bg-[#26242C] ${
|
className={`hidden absolute top-0 left-7.5 right-7.5 h-0.25 bg-[#26242C] ${
|
||||||
crossesOffset && crossesOffset
|
crossesOffset && crossesOffset
|
||||||
} pointer-events-none lg:block xl:left-16 right-16`}
|
} pointer-events-none lg:block xl:left-16 right-16`}
|
||||||
/>
|
/>
|
||||||
<SectionSvg crossesOffset={crossesOffset} />
|
<SectionSvg crossesOffset={crossesOffset} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Section;
|
export default Section;
|
||||||
|
|||||||
@@ -9,53 +9,53 @@ import { PulicBetaBadge } from "./beta/badge";
|
|||||||
const hideNavbar = false;
|
const hideNavbar = false;
|
||||||
|
|
||||||
export const Navbar = () => {
|
export const Navbar = () => {
|
||||||
return (
|
return (
|
||||||
<nav className="md:grid grid-cols-12 border-b sticky top-0 flex items-center justify-between bg-background backdrop-blur-md z-30">
|
<nav className="md:grid grid-cols-12 border-b sticky top-0 flex items-center justify-between bg-background backdrop-blur-md z-30">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
className="md:border-r md:px-5 px-2.5 py-4 text-foreground md:col-span-2 shrink-0 transition-colors md:w-[--fd-sidebar-width]"
|
className="md:border-r md:px-5 px-2.5 py-4 text-foreground md:col-span-2 shrink-0 transition-colors md:w-[--fd-sidebar-width]"
|
||||||
>
|
>
|
||||||
<div className="flex flex-col gap-2 w-full">
|
<div className="flex flex-col gap-2 w-full">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Logo />
|
<Logo />
|
||||||
<p>BETTER-AUTH.</p>
|
<p>BETTER-AUTH.</p>
|
||||||
</div>
|
</div>
|
||||||
{/* <PulicBetaBadge /> */}
|
{/* <PulicBetaBadge /> */}
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="md:col-span-10 flex items-center justify-end">
|
<div className="md:col-span-10 flex items-center justify-end">
|
||||||
<ul className="md:flex items-center divide-x w-max border-r hidden shrink-0">
|
<ul className="md:flex items-center divide-x w-max border-r hidden shrink-0">
|
||||||
{hideNavbar
|
{hideNavbar
|
||||||
? null
|
? null
|
||||||
: navMenu.map((menu, i) => (
|
: navMenu.map((menu, i) => (
|
||||||
<NavLink key={menu.name} href={menu.path}>
|
<NavLink key={menu.name} href={menu.path}>
|
||||||
{menu.name}
|
{menu.name}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
<NavbarMobileBtn />
|
<NavbarMobileBtn />
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const navMenu = [
|
export const navMenu = [
|
||||||
{
|
{
|
||||||
name: "helo_",
|
name: "helo_",
|
||||||
path: "/",
|
path: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "docs",
|
name: "docs",
|
||||||
path: "/docs",
|
path: "/docs",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "changelogs",
|
name: "changelogs",
|
||||||
path: "/changelogs",
|
path: "/changelogs",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "community",
|
name: "community",
|
||||||
path: "https://discord.gg/GYC3W7tZzb",
|
path: "https://discord.gg/GYC3W7tZzb",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -33,12 +33,18 @@ description: Apple
|
|||||||
provider: "sqlite",
|
provider: "sqlite",
|
||||||
url: "./db.sqlite",
|
url: "./db.sqlite",
|
||||||
},
|
},
|
||||||
socialProvider: { // [!code highlight]
|
socialProvider: [ // [!code highlight]
|
||||||
apple: { // [!code highlight]
|
apple({ // [!code highlight]
|
||||||
clientId: process.env.APPLE_CLIENT_ID as string, // [!code highlight]
|
clientId: process.env.APPLE_CLIENT_ID as string, // [!code highlight]
|
||||||
clientSecret: process.env.APPLE_CLIENT_SECRET as string, // [!code highlight]
|
clientSecret: process.env.APPLE_CLIENT_SECRET as string, // [!code highlight]
|
||||||
} // [!code highlight]
|
/** // [!code highlight]
|
||||||
}, // [!code highlight]
|
* this is optional. // [!code highlight]
|
||||||
|
* only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
|
||||||
|
* or if you're using a custom domain. // [!code highlight]
|
||||||
|
*/ // [!code highlight]
|
||||||
|
redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
|
||||||
|
}), // [!code highlight]
|
||||||
|
], // [!code highlight]
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
</Step>
|
</Step>
|
||||||
|
|||||||
@@ -2,5 +2,8 @@ import { clsx, type ClassValue } from "clsx";
|
|||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
|
export function absoluteUrl(path: string) {
|
||||||
|
return `${process.env.NEXT_PUBLIC_APP_URL}${path}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
"@tsparticles/engine": "^3.5.0",
|
"@tsparticles/engine": "^3.5.0",
|
||||||
"@tsparticles/react": "^3.0.0",
|
"@tsparticles/react": "^3.0.0",
|
||||||
"@tsparticles/slim": "^3.5.0",
|
"@tsparticles/slim": "^3.5.0",
|
||||||
|
"@vercel/og": "^0.6.3",
|
||||||
"better-auth": "workspace:*",
|
"better-auth": "workspace:*",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
|||||||
18065
pnpm-lock.yaml
generated
18065
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user