chore: merge remote-tracking branch 'origin/main' into dev
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "autumndev",
|
||||
@@ -10,7 +11,7 @@
|
||||
"lottie-react": "^2.4.1",
|
||||
"matter-js": "^0.20.0",
|
||||
"motion": "^12.38.0",
|
||||
"next": "16.2.1",
|
||||
"next": "16.2.4",
|
||||
"next-mdx-remote": "^6.0.0",
|
||||
"ngrok": "^5.0.0-beta.2",
|
||||
"react": "19.2.4",
|
||||
@@ -163,25 +164,25 @@
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
||||
|
||||
"@next/env": ["@next/env@16.2.1", "", {}, "sha512-n8P/HCkIWW+gVal2Z8XqXJ6aB3J0tuM29OcHpCsobWlChH/SITBs1DFBk/HajgrwDkqqBXPbuUuzgDvUekREPg=="],
|
||||
"@next/env": ["@next/env@16.2.4", "", {}, "sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw=="],
|
||||
|
||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.2.1", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-r0epZGo24eT4g08jJlg2OEryBphXqO8aL18oajoTKLzHJ6jVr6P6FI58DLMug04MwD3j8Fj0YK0slyzneKVyzA=="],
|
||||
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BwZ8w8YTaSEr2HIuXLMLxIdElNMPvY9fLqb20LX9A9OMGtJilhHLbCL3ggyd0TwjmMcTxi0XXt+ur1vWUoxj2Q=="],
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OXTFFox5EKN1Ym08vfrz+OXxmCcEjT4SFMbNRsWZE99dMqt2Kcusl5MqPXcW232RYkMLQTy0hqgAMEsfEd/l2A=="],
|
||||
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/vrcE6iQSJq3uL3VGVHiXeaKbn8Es10DGTGRJnRZlkNQQk3kaNtAJg8Y6xuAlrx/6INKVjkfi5rY0iEXorZ6uA=="],
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-XhpVnUfmYWvD3YrXu55XdcAkQtOnvaI6wtQa8fuF5fGoKoxIUZ0kWPtcOfqJEWngFF/lOS9l3+O9CcownhiQxQ=="],
|
||||
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-uLn+0BK+C31LTVbQ/QU+UaVrV0rRSJQ8RfniQAHPghDdgE+SlroYqcmFnO5iNjNfVWCyKZHYrs3Nl0mUzWxbBw=="],
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-Mx/tjlNA3G8kg14QvuGAJ4xBwPk1tUHq56JxZ8CXnZwz1Etz714soCEzGQQzVMz4bEnGPowzkV6Xrp6wAkEWOQ=="],
|
||||
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ssKq6iMRnHdnycGp9hCuGnXJZ0YPr4/wNwrfE5DbmvEcgl9+yv97/Kq3TPVDfYome1SW5geciLB9aiEqKXQjlQ=="],
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-iVMMp14514u7Nup2umQS03nT/bN9HurK8ufylC3FZNykrwjtx7V1A7+4kvhbDSCeonTVqV3Txnv0Lu+m2oDXNg=="],
|
||||
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HQm7SrHRELJ30T1TSmT706IWovFFSRGxfgUkyWJZF/RKBMdbdRWJuFrcpDdE5vy9UXjFOx6L3mRdqH04Mmx0hg=="],
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-EZOvm1aQWgnI/N/xcWOlnS3RQBk0VtVav5Zo7n4p0A7UKyTDx047k8opDbXgBpHl4CulRqRfbw3QrX2w5UOXMQ=="],
|
||||
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-aV2iUaC/5HGEpbBkE+4B8aHIudoOy5DYekAKOMSHoIYQ66y/wIVeaRx8MS2ZMdxe/HIXlMho4ubdZs/J8441Tg=="],
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-h9FxsngCm9cTBf71AR4fGznDEDx1hS7+kSEiIRjq5kO1oXWm07DxVGZjCvk0SGx7TSjlUqhI8oOyz7NfwAdPoA=="],
|
||||
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-IXdNgiDHaSk0ZUJ+xp0OQTdTgnpx1RCfRTalhn3cjOP+IddTMINwA7DXZrwTmGDO8SUr5q2hdP/du4DcrB1GxA=="],
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-3NdJV5OXMSOeJYijX+bjaLge3mJBlh4ybydbT4GFoB/2hAojWHtMhl3CYlYoMrjPuodp0nzFVi4Tj2+WaMg+Ow=="],
|
||||
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-qvU+3a39Hay+ieIztkGSbF7+mccbbg1Tk25hc4JDylf8IHjYmY/Zm64Qq1602yPyQqvie+vf5T/uPwNxDNIoeg=="],
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-kMVGgsqhO5YTYODD9IPGGhA6iprWidQckK3LmPeW08PIFENRmgfb4MjXHO+p//d+ts2rpjvK5gXWzXSMrPl9cw=="],
|
||||
|
||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||
|
||||
@@ -913,7 +914,7 @@
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"next": ["next@16.2.1", "", { "dependencies": { "@next/env": "16.2.1", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.1", "@next/swc-darwin-x64": "16.2.1", "@next/swc-linux-arm64-gnu": "16.2.1", "@next/swc-linux-arm64-musl": "16.2.1", "@next/swc-linux-x64-gnu": "16.2.1", "@next/swc-linux-x64-musl": "16.2.1", "@next/swc-win32-arm64-msvc": "16.2.1", "@next/swc-win32-x64-msvc": "16.2.1", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": "dist/bin/next" }, "sha512-VaChzNL7o9rbfdt60HUj8tev4m6d7iC1igAy157526+cJlXOQu5LzsBXNT+xaJnTP/k+utSX5vMv7m0G+zKH+Q=="],
|
||||
"next": ["next@16.2.4", "", { "dependencies": { "@next/env": "16.2.4", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.4", "@next/swc-darwin-x64": "16.2.4", "@next/swc-linux-arm64-gnu": "16.2.4", "@next/swc-linux-arm64-musl": "16.2.4", "@next/swc-linux-x64-gnu": "16.2.4", "@next/swc-linux-x64-musl": "16.2.4", "@next/swc-win32-arm64-msvc": "16.2.4", "@next/swc-win32-x64-msvc": "16.2.4", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-kPvz56wF5frc+FxlHI5qnklCzbq53HTwORaWBGdT0vNoKh1Aya9XC8aPauH4NJxqtzbWsS5mAbctm4cr+EkQ2Q=="],
|
||||
|
||||
"next-mdx-remote": ["next-mdx-remote@6.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ=="],
|
||||
|
||||
|
||||
@@ -1,284 +1,307 @@
|
||||
"use client";
|
||||
|
||||
import { CTALines, IconCTADocs, IconCTAStart } from "@/app/constant";
|
||||
import { useGSAP } from "@gsap/react";
|
||||
import gsap from "gsap";
|
||||
import { motion } from "motion/react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { CTALines, IconCTADocs, IconCTAStart } from "@/app/constant";
|
||||
import AutumnConfig from "./autumn-config";
|
||||
|
||||
// import dynamic from "next/dynamic";
|
||||
|
||||
// const AutumnConfig = dynamic(() => import("./autumn-config"), { ssr: false });
|
||||
|
||||
const BADGE_TEXT = "// 100% open source";
|
||||
|
||||
const getLoggedInHintCookie = () => {
|
||||
if (typeof window === "undefined") return null;
|
||||
return (
|
||||
document.cookie
|
||||
.split("; ")
|
||||
.find((row) => row.startsWith("logged_in_hint="))
|
||||
?.split("=")[1] === "1"
|
||||
);
|
||||
};
|
||||
|
||||
export default function Hero() {
|
||||
const containerRef = useRef(null);
|
||||
const heroTlRef = useRef(null);
|
||||
const [displayedText, setDisplayedText] = useState("");
|
||||
const containerRef = useRef(null);
|
||||
const heroTlRef = useRef(null);
|
||||
const [displayedText, setDisplayedText] = useState("");
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
|
||||
// Badge typewriter
|
||||
useEffect(() => {
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*0123456789";
|
||||
let intervalId;
|
||||
let timeoutId;
|
||||
// Read the hint cookie after mount to avoid SSR/CSR hydration mismatch.
|
||||
useEffect(() => {
|
||||
setIsLoggedIn(getLoggedInHintCookie() === true);
|
||||
}, []);
|
||||
|
||||
const startTypewriter = () => {
|
||||
timeoutId = setTimeout(() => {
|
||||
let iteration = 0;
|
||||
intervalId = setInterval(() => {
|
||||
setDisplayedText(
|
||||
BADGE_TEXT.split("")
|
||||
.map((char, index) => {
|
||||
if (char === " ") return " ";
|
||||
if (index < Math.floor(iteration)) return char;
|
||||
if (index === Math.floor(iteration))
|
||||
return chars[Math.floor(Math.random() * chars.length)];
|
||||
return "";
|
||||
})
|
||||
.join(""),
|
||||
);
|
||||
// Badge typewriter
|
||||
useEffect(() => {
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*0123456789";
|
||||
let intervalId;
|
||||
let timeoutId;
|
||||
|
||||
iteration += 0.4;
|
||||
const startTypewriter = () => {
|
||||
timeoutId = setTimeout(() => {
|
||||
let iteration = 0;
|
||||
intervalId = setInterval(() => {
|
||||
setDisplayedText(
|
||||
BADGE_TEXT.split("")
|
||||
.map((char, index) => {
|
||||
if (char === " ") return " ";
|
||||
if (index < Math.floor(iteration)) return char;
|
||||
if (index === Math.floor(iteration))
|
||||
return chars[Math.floor(Math.random() * chars.length)];
|
||||
return "";
|
||||
})
|
||||
.join(""),
|
||||
);
|
||||
|
||||
if (iteration >= BADGE_TEXT.length) {
|
||||
clearInterval(intervalId);
|
||||
setDisplayedText(BADGE_TEXT);
|
||||
}
|
||||
}, 30);
|
||||
}, 150);
|
||||
};
|
||||
iteration += 0.4;
|
||||
|
||||
window.addEventListener("preloader:complete", startTypewriter, {
|
||||
once: true,
|
||||
});
|
||||
return () => {
|
||||
window.removeEventListener("preloader:complete", startTypewriter);
|
||||
clearTimeout(timeoutId);
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, []);
|
||||
if (iteration >= BADGE_TEXT.length) {
|
||||
clearInterval(intervalId);
|
||||
setDisplayedText(BADGE_TEXT);
|
||||
}
|
||||
}, 30);
|
||||
}, 150);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handler = () => heroTlRef.current?.play();
|
||||
window.addEventListener("preloader:complete", handler, { once: true });
|
||||
return () => window.removeEventListener("preloader:complete", handler);
|
||||
}, []);
|
||||
window.addEventListener("preloader:complete", startTypewriter, {
|
||||
once: true,
|
||||
});
|
||||
return () => {
|
||||
window.removeEventListener("preloader:complete", startTypewriter);
|
||||
clearTimeout(timeoutId);
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useGSAP(
|
||||
() => {
|
||||
gsap.set(".hero-root", { opacity: 0 });
|
||||
useEffect(() => {
|
||||
const handler = () => heroTlRef.current?.play();
|
||||
window.addEventListener("preloader:complete", handler, { once: true });
|
||||
return () => window.removeEventListener("preloader:complete", handler);
|
||||
}, []);
|
||||
|
||||
gsap.set(".hero-bg", {
|
||||
opacity: 0,
|
||||
filter: "blur(6px) brightness(1)",
|
||||
scale: 0.97,
|
||||
transformOrigin: "center top",
|
||||
});
|
||||
useGSAP(
|
||||
() => {
|
||||
gsap.set(".hero-root", { opacity: 0 });
|
||||
|
||||
gsap.set(".hero-reveal", {
|
||||
opacity: 0,
|
||||
y: 25,
|
||||
filter: "blur(12px)",
|
||||
scale: 0.96,
|
||||
transformOrigin: "center bottom",
|
||||
});
|
||||
gsap.set(".hero-bg", {
|
||||
opacity: 0,
|
||||
filter: "blur(6px) brightness(1)",
|
||||
scale: 0.97,
|
||||
transformOrigin: "center top",
|
||||
});
|
||||
|
||||
gsap.set(".hero-cta", { opacity: 0, scale: 0.95 });
|
||||
gsap.set(".hero-reveal", {
|
||||
opacity: 0,
|
||||
y: 25,
|
||||
filter: "blur(12px)",
|
||||
scale: 0.96,
|
||||
transformOrigin: "center bottom",
|
||||
});
|
||||
|
||||
const tl = gsap.timeline({
|
||||
paused: true,
|
||||
defaults: { overwrite: "auto" },
|
||||
});
|
||||
heroTlRef.current = tl;
|
||||
gsap.set(".hero-cta", { opacity: 0, scale: 0.95 });
|
||||
|
||||
tl.to(".hero-root", { opacity: 1, duration: 0.3, ease: "none" })
|
||||
const tl = gsap.timeline({
|
||||
paused: true,
|
||||
defaults: { overwrite: "auto" },
|
||||
});
|
||||
heroTlRef.current = tl;
|
||||
|
||||
.to(".hero-bg", {
|
||||
opacity: 1,
|
||||
filter: "blur(0px) brightness(1)",
|
||||
scale: 1,
|
||||
duration: 0.4,
|
||||
ease: "power2.out",
|
||||
})
|
||||
tl.to(".hero-root", { opacity: 1, duration: 0.3, ease: "none" })
|
||||
|
||||
.to(".hero-bg", {
|
||||
filter: "blur(0px) brightness(1.6)",
|
||||
duration: 0.125,
|
||||
ease: "power2.in",
|
||||
})
|
||||
.to(".hero-bg", {
|
||||
opacity: 1,
|
||||
filter: "blur(0px) brightness(1)",
|
||||
scale: 1,
|
||||
duration: 0.4,
|
||||
ease: "power2.out",
|
||||
})
|
||||
|
||||
.to(".hero-bg", {
|
||||
filter: "blur(0px) brightness(1)",
|
||||
duration: 0.125,
|
||||
ease: "power2.out",
|
||||
})
|
||||
.to(".hero-bg", {
|
||||
filter: "blur(0px) brightness(1.6)",
|
||||
duration: 0.125,
|
||||
ease: "power2.in",
|
||||
})
|
||||
|
||||
.to(
|
||||
".hero-reveal",
|
||||
{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
filter: "blur(0px)",
|
||||
scale: 1,
|
||||
duration: 1.1,
|
||||
stagger: 0.1,
|
||||
ease: "power3.out",
|
||||
},
|
||||
"-=0.2",
|
||||
)
|
||||
.to(".hero-bg", {
|
||||
filter: "blur(0px) brightness(1)",
|
||||
duration: 0.125,
|
||||
ease: "power2.out",
|
||||
})
|
||||
|
||||
.to(
|
||||
".hero-cta",
|
||||
{
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
duration: 0.3,
|
||||
stagger: 0.06,
|
||||
ease: "back.out(1.5)",
|
||||
},
|
||||
"-=0.1",
|
||||
);
|
||||
},
|
||||
{ scope: containerRef },
|
||||
);
|
||||
.to(
|
||||
".hero-reveal",
|
||||
{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
filter: "blur(0px)",
|
||||
scale: 1,
|
||||
duration: 1.1,
|
||||
stagger: 0.1,
|
||||
ease: "power3.out",
|
||||
},
|
||||
"-=0.2",
|
||||
)
|
||||
|
||||
return (
|
||||
<div ref={containerRef}>
|
||||
<div className="relative hero-root opacity-0 flex flex-col items-stretch pb-0 md:pb-12 mb-0 bg-[#0F0F0F]">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex flex-col gap-6 px-4 xl:px-22.75 py-8 bg-[#0F0F0F] mt-26">
|
||||
<h4 className="hero-reveal relative uppercase font-mono tracking-[-2%] text-[12px] md:text-sm leading-sm text-white md:text-[#FFFFFF99] bg-[#2c2c2d] w-fit p-2 min-h-[30px] md:min-h-[36px] flex items-center">
|
||||
<span className="invisible select-none" aria-hidden="true">
|
||||
{BADGE_TEXT}
|
||||
</span>
|
||||
<span className="absolute inset-0 flex items-center p-2">
|
||||
{displayedText}
|
||||
</span>
|
||||
</h4>
|
||||
<div className="flex flex-col gap-6 w-full px-0 lg:px-0">
|
||||
<h1 className="hero-reveal text-[44px] md:text-[56px] w-full max-w-sm sm:max-w-[480px] md:max-w-xl leading-[44px] tracking-[-5%] md:leading-14 font-sans">
|
||||
<span className="text-[#FFFFFF99] font-normal">
|
||||
The drop-in billing layer for
|
||||
</span>{" "}
|
||||
<span className="text-white block md:inline">AI startups</span>
|
||||
</h1>
|
||||
<p className="hero-reveal tracking-[-2%] w-full max-w-xs sm:max-w-[480px] md:max-w-xl text-[#FFFFFF99] md:text-[16px] text-[14px] font-light leading-5 font-sans">
|
||||
Stop rebuilding usage limits, credit ledgers and payment
|
||||
logic.{" "}
|
||||
<span className="text-white font-light">
|
||||
Autumn is your customer database
|
||||
</span>{" "}
|
||||
that scales from your first user to your largest contract.
|
||||
</p>
|
||||
</div>
|
||||
.to(
|
||||
".hero-cta",
|
||||
{
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
duration: 0.3,
|
||||
stagger: 0.06,
|
||||
ease: "back.out(1.5)",
|
||||
},
|
||||
"-=0.1",
|
||||
);
|
||||
},
|
||||
{ scope: containerRef },
|
||||
);
|
||||
|
||||
</div>
|
||||
<div className="hero-reveal relative w-[50vw] max-w-[720px] p-16 py-0 mx-auto hidden xl:block">
|
||||
<div className="absolute inset-0 z-0 pointer-events-none">
|
||||
<video
|
||||
src="/images/pricing-models/pricingbg.webm"
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="absolute inset-0 w-full h-full object-cover mix-blend-screen opacity-100"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative z-10 translate-y-16 w-full flex justify-center">
|
||||
<AutumnConfig initialDelay={200} awaitEvent="preloader:complete" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-[#292929]" />
|
||||
<div className="flex flex-nowrap items-center xl:px-22.75 px-4 bg-[#0F0F0F] w-full overflow-hidden">
|
||||
{/* Primary CTA */}
|
||||
<div className="hero-cta w-full md:w-fit md:flex-shrink-0">
|
||||
<Link href={"https://app.useautumn.com/sign-in"}>
|
||||
<motion.div
|
||||
initial="initial"
|
||||
whileHover="hover"
|
||||
whileTap="hover"
|
||||
className="relative"
|
||||
>
|
||||
{/* Adjusted px-3 for mobile, md:px-4 for desktop */}
|
||||
<div className="relative overflow-hidden flex items-center gap-1.5 md:gap-2.5 cursor-pointer justify-between py-2 px-3 md:px-4 md:py-3.5 md:w-50 font-sans bg-[#9564ff] hover:bg-[#7D46F4] transition-colors duration-300">
|
||||
<CTALines />
|
||||
<span className="relative z-10 tracking-[-2%] uppercase md:normal-case text-white font-medium text-[12px] md:text-base whitespace-nowrap">
|
||||
Start for free
|
||||
</span>
|
||||
<span className="relative z-10 scale-95 md:scale-100">
|
||||
<IconCTAStart />
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Link>
|
||||
</div>
|
||||
return (
|
||||
<div ref={containerRef}>
|
||||
<div className="relative hero-root opacity-0 flex flex-col items-stretch pb-0 md:pb-12 mb-0 bg-[#0F0F0F]">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex flex-col gap-6 px-4 xl:px-22.75 py-8 bg-[#0F0F0F] mt-26">
|
||||
<h4 className="hero-reveal relative uppercase font-mono tracking-[-2%] text-[12px] md:text-sm leading-sm text-white md:text-[#FFFFFF99] bg-[#2c2c2d] w-fit p-2 min-h-[30px] md:min-h-[36px] flex items-center">
|
||||
<span className="invisible select-none" aria-hidden="true">
|
||||
{BADGE_TEXT}
|
||||
</span>
|
||||
<span className="absolute inset-0 flex items-center p-2">
|
||||
{displayedText}
|
||||
</span>
|
||||
</h4>
|
||||
<div className="flex flex-col gap-6 w-full px-0 lg:px-0">
|
||||
<h1 className="hero-reveal text-[44px] md:text-[56px] w-full max-w-sm sm:max-w-[480px] md:max-w-xl leading-[44px] tracking-[-5%] md:leading-14 font-sans">
|
||||
<span className="text-[#FFFFFF99] font-normal">
|
||||
The drop-in billing layer for
|
||||
</span>{" "}
|
||||
<span className="text-white block md:inline">AI startups</span>
|
||||
</h1>
|
||||
<p className="hero-reveal tracking-[-2%] w-full max-w-xs sm:max-w-[480px] md:max-w-xl text-[#FFFFFF99] md:text-[16px] text-[14px] font-light leading-5 font-sans">
|
||||
Stop rebuilding usage limits, credit ledgers and payment logic.{" "}
|
||||
<span className="text-white font-light">
|
||||
Autumn is your customer database
|
||||
</span>{" "}
|
||||
that scales from your first user to your largest contract.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hero-reveal relative w-[50vw] max-w-[720px] p-16 py-0 mx-auto hidden xl:block">
|
||||
<div className="absolute inset-0 z-0 pointer-events-none">
|
||||
<video
|
||||
src="/images/pricing-models/pricingbg.webm"
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="absolute inset-0 w-full h-full object-cover mix-blend-screen opacity-100"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative z-10 translate-y-16 w-full flex justify-center">
|
||||
<AutumnConfig
|
||||
initialDelay={200}
|
||||
awaitEvent="preloader:complete"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-[#292929]" />
|
||||
<div className="flex flex-nowrap items-center xl:px-22.75 px-4 bg-[#0F0F0F] w-full overflow-hidden">
|
||||
{/* Primary CTA */}
|
||||
<div className="hero-cta w-full md:w-fit md:flex-shrink-0">
|
||||
<Link
|
||||
href={
|
||||
isLoggedIn
|
||||
? "https://app.useautumn.com"
|
||||
: "https://app.useautumn.com/sign-in"
|
||||
}
|
||||
>
|
||||
<motion.div
|
||||
initial="initial"
|
||||
whileHover="hover"
|
||||
whileTap="hover"
|
||||
className="relative"
|
||||
>
|
||||
{/* Adjusted px-3 for mobile, md:px-4 for desktop */}
|
||||
<div className="relative overflow-hidden flex items-center gap-1.5 md:gap-2.5 cursor-pointer justify-between py-2 px-3 md:px-4 md:py-3.5 md:w-50 font-sans bg-[#9564ff] hover:bg-[#7D46F4] transition-colors duration-300">
|
||||
<CTALines />
|
||||
<span className="relative z-10 tracking-[-2%] uppercase md:normal-case text-white font-medium text-[12px] md:text-base whitespace-nowrap">
|
||||
{isLoggedIn ? "Dashboard" : "Start for free"}
|
||||
</span>
|
||||
<span className="relative z-10 scale-95 md:scale-100">
|
||||
<IconCTAStart />
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Secondary CTA */}
|
||||
<div className="hero-cta w-full md:w-fit md:flex-shrink-0">
|
||||
<Link href={"https://cal.com/ayrod"}>
|
||||
<motion.div
|
||||
initial="initial"
|
||||
whileHover="hover"
|
||||
whileTap="hover"
|
||||
className="relative"
|
||||
>
|
||||
<div className="relative overflow-hidden flex items-center gap-1.5 md:gap-2.5 border-r border-[#292929] text-white cursor-pointer justify-between py-2 px-3 md:px-4 md:py-3.5 md:w-50 font-sans bg-[#0F0F0F] hover:bg-[#FFFFFF1F] transition-colors duration-300">
|
||||
<CTALines />
|
||||
<span className="relative z-10 tracking-[-2%] text-[12px] uppercase md:normal-case md:text-[16px] whitespace-nowrap">
|
||||
Book a call
|
||||
</span>
|
||||
<span className="relative z-10 scale-100">
|
||||
<IconCTADocs />
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Secondary CTA */}
|
||||
<div className="hero-cta w-full md:w-fit md:flex-shrink-0">
|
||||
<Link href={"https://cal.com/ayrod"}>
|
||||
<motion.div
|
||||
initial="initial"
|
||||
whileHover="hover"
|
||||
whileTap="hover"
|
||||
className="relative"
|
||||
>
|
||||
<div className="relative overflow-hidden flex items-center gap-1.5 md:gap-2.5 border-r border-[#292929] text-white cursor-pointer justify-between py-2 px-3 md:px-4 md:py-3.5 md:w-50 font-sans bg-[#0F0F0F] hover:bg-[#FFFFFF1F] transition-colors duration-300">
|
||||
<CTALines />
|
||||
<span className="relative z-10 tracking-[-2%] text-[12px] uppercase md:normal-case md:text-[16px] whitespace-nowrap">
|
||||
Book a call
|
||||
</span>
|
||||
<span className="relative z-10 scale-100">
|
||||
<IconCTADocs />
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="hero-cta hidden md:flex flex-nowrap gap-2 md:gap-3 ml-2 md:ml-3 h-10.5 md:h-12.5 flex-1">
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="hero-cta hidden md:flex flex-nowrap gap-2 md:gap-3 ml-2 md:ml-3 h-10.5 md:h-12.5 flex-1">
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-b border-[#292929]" />
|
||||
{/* MOBILE VIEW*/}
|
||||
<div className="relative block xl:hidden w-full overflow-hidden bg-[#0F0F0F] mt-12">
|
||||
<div className="relative overflow-hidden w-full p-7 flex items-center justify-center">
|
||||
<video
|
||||
src="/images/pricing-models/pricingbg.webm"
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="hero-bg absolute inset-0 w-full h-full object-cover mix-blend-screen opacity-100"
|
||||
/>
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
<div className="border-r border-[#292929] h-full hidden md:block" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-b border-[#292929]" />
|
||||
{/* MOBILE VIEW*/}
|
||||
<div className="relative block xl:hidden w-full overflow-hidden bg-[#0F0F0F] mt-12">
|
||||
<div className="relative overflow-hidden w-full p-7 flex items-center justify-center">
|
||||
<video
|
||||
src="/images/pricing-models/pricingbg.webm"
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="hero-bg absolute inset-0 w-full h-full object-cover mix-blend-screen opacity-100"
|
||||
/>
|
||||
|
||||
<div className="hero-reveal relative z-10 w-[96%] sm:w-[90%] max-w-[520px] flex justify-center items-center">
|
||||
{/* <AutumnConfig lines={16} initialDelay={1000} awaitEvent="preloader:complete" /> */}
|
||||
<Image
|
||||
src={"/images/hero/autumn_mobile.svg"}
|
||||
width={1600}
|
||||
height={1600}
|
||||
alt="xyz"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
<div className="hero-reveal relative z-10 w-[96%] sm:w-[90%] max-w-[520px] flex justify-center items-center">
|
||||
{/* <AutumnConfig lines={16} initialDelay={1000} awaitEvent="preloader:complete" /> */}
|
||||
<Image
|
||||
src={"/images/hero/autumn_mobile.svg"}
|
||||
width={1600}
|
||||
height={1600}
|
||||
alt="xyz"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
1757
apps/website/package-lock.json
generated
1757
apps/website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,32 @@
|
||||
{
|
||||
"name": "autumndev",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3004",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gsap/react": "^2.1.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"gsap": "^3.14.2",
|
||||
"lottie-react": "^2.4.1",
|
||||
"matter-js": "^0.20.0",
|
||||
"motion": "^12.38.0",
|
||||
"next": "16.2.1",
|
||||
"next-mdx-remote": "^6.0.0",
|
||||
"ngrok": "^5.0.0-beta.2",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"react-syntax-highlighter": "^16.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.2.2",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.2.1",
|
||||
"tailwindcss": "^4.2.2"
|
||||
}
|
||||
"name": "@autumn/website",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3004",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gsap/react": "^2.1.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"gsap": "^3.14.2",
|
||||
"lottie-react": "^2.4.1",
|
||||
"matter-js": "^0.20.0",
|
||||
"motion": "^12.38.0",
|
||||
"next": "16.2.4",
|
||||
"next-mdx-remote": "^6.0.0",
|
||||
"ngrok": "^5.0.0-beta.2",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"react-syntax-highlighter": "^16.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.2.2",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.2.1",
|
||||
"tailwindcss": "^4.2.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ COPY packages/stripe-sync/package.json ./packages/stripe-sync/package.json
|
||||
COPY packages/sdk/package.json ./packages/sdk/package.json
|
||||
COPY apps/sdk-test/package.json ./apps/sdk-test/package.json
|
||||
COPY apps/docs/package.json ./apps/docs/package.json
|
||||
COPY apps/website/package.json ./apps/website/package.json
|
||||
|
||||
# Install dependencies
|
||||
RUN bun install --ignore-scripts
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"scripts",
|
||||
"apps/checkout",
|
||||
"apps/docs",
|
||||
"apps/website",
|
||||
"apps/sdk-test",
|
||||
"packages/atmn",
|
||||
"packages/atmn-tests",
|
||||
@@ -99,7 +100,7 @@
|
||||
"svix:push": "infisical run --env=dev -- bun packages/openapi/scripts/svixPush.ts",
|
||||
"svix:push:prod": "infisical run --env=prod -- bun packages/openapi/scripts/svixPush.ts",
|
||||
"docs:pull": "bun -F @autumn/docs pull",
|
||||
"site": "cd apps/website && npm install && npm run dev",
|
||||
"site": "cd apps/website && bun dev && cd ../..",
|
||||
"docs": "bun -F @autumn/docs dev",
|
||||
"docs:build": "bun -F @autumn/docs build",
|
||||
"ts": "bun -F @autumn/server ts && bun -F autumn-js ts && bun -F @autumn/openapi ts && bun -F atmn ts && bun -F checkout ts",
|
||||
|
||||
@@ -55,6 +55,8 @@ export const computeAttachPlan = ({
|
||||
params,
|
||||
});
|
||||
|
||||
const includeArrearLineItems = !params.carry_over_usages?.enabled;
|
||||
|
||||
const { allLineItems: lineItems, updateCustomerEntitlements } =
|
||||
planTiming === "immediate"
|
||||
? buildAutumnLineItems({
|
||||
@@ -62,7 +64,7 @@ export const computeAttachPlan = ({
|
||||
newCustomerProducts: [newCustomerProduct],
|
||||
deletedCustomerProduct: currentCustomerProduct,
|
||||
billingContext: attachBillingContext,
|
||||
includeArrearLineItems: true,
|
||||
includeArrearLineItems,
|
||||
})
|
||||
: { allLineItems: [], updateCustomerEntitlements: [] };
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ import { sendInvitationEmail } from "@/internal/emails/sendInvitationEmail.js";
|
||||
import { sendOnboardingEmail } from "@/internal/emails/sendOnboardingEmail.js";
|
||||
import sendOTPEmail from "@/internal/emails/sendOTPEmail.js";
|
||||
import { afterOrgCreated } from "./authUtils/afterOrgCreated.js";
|
||||
import { afterSessionCreated } from "./authUtils/afterSessionCreated.js";
|
||||
import { afterSessionDeleted } from "./authUtils/afterSessionDeleted.js";
|
||||
import { beforeSessionCreated } from "./authUtils/beforeSessionCreated.js";
|
||||
import { ADMIN_USER_IDs } from "./constants.js";
|
||||
|
||||
@@ -48,6 +50,14 @@ export const auth = betterAuth({
|
||||
session: {
|
||||
create: {
|
||||
before: beforeSessionCreated,
|
||||
after: (session, context) => {
|
||||
return afterSessionCreated(session, context);
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
after: (session, context) => {
|
||||
return afterSessionDeleted(session, context);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
28
server/src/utils/authUtils/afterSessionCreated.ts
Normal file
28
server/src/utils/authUtils/afterSessionCreated.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { GenericEndpointContext } from "@better-auth/core";
|
||||
import type { BetterAuthOptions, Session } from "better-auth";
|
||||
|
||||
export const afterSessionCreated = async (
|
||||
session: Session,
|
||||
context: GenericEndpointContext<BetterAuthOptions> | null,
|
||||
) => {
|
||||
try {
|
||||
if (!context) return;
|
||||
|
||||
// In dev, the Vite dashboard sets this cookie client-side (localhost
|
||||
// doesn't support cross-port cookie sharing via Set-Cookie headers).
|
||||
if (process.env.NODE_ENV !== "production") return;
|
||||
|
||||
// Set a non-httpOnly hint cookie on the root domain so the landing
|
||||
// page (useautumn.com) can detect that the user is logged in on app.useautumn.com.
|
||||
context.setCookie("logged_in_hint", "1", {
|
||||
domain: ".useautumn.com",
|
||||
path: "/",
|
||||
maxAge: 60 * 60 * 24 * 7, // 7 days
|
||||
secure: true,
|
||||
sameSite: "none",
|
||||
httpOnly: false,
|
||||
});
|
||||
} catch (_) {
|
||||
console.error("Error running afterSessionCreated", { error: _ });
|
||||
}
|
||||
};
|
||||
29
server/src/utils/authUtils/afterSessionDeleted.ts
Normal file
29
server/src/utils/authUtils/afterSessionDeleted.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { GenericEndpointContext } from "@better-auth/core";
|
||||
import type { BetterAuthOptions, Session } from "better-auth";
|
||||
|
||||
export const afterSessionDeleted = async (
|
||||
_session: Session,
|
||||
context: GenericEndpointContext<BetterAuthOptions> | null,
|
||||
) => {
|
||||
try {
|
||||
if (!context) return;
|
||||
|
||||
// Dev parity: the cookie is only set server-side in production, so
|
||||
// we don't need to clear it here in other environments.
|
||||
if (process.env.NODE_ENV !== "production") return;
|
||||
|
||||
// Clear the landing-page hint cookie so signed-out users stop seeing
|
||||
// the "Dashboard" CTA on useautumn.com. Attributes must match the
|
||||
// original setCookie call so the browser overwrites the cookie.
|
||||
context.setCookie("logged_in_hint", "", {
|
||||
domain: ".useautumn.com",
|
||||
path: "/",
|
||||
maxAge: 0,
|
||||
secure: true,
|
||||
sameSite: "none",
|
||||
httpOnly: false,
|
||||
});
|
||||
} catch (_) {
|
||||
console.error("Error running afterSessionDeleted", { error: _ });
|
||||
}
|
||||
};
|
||||
@@ -51,6 +51,17 @@ export default function App() {
|
||||
Sentry.setTags({
|
||||
org_id: data.session.activeOrganizationId ?? "unknown_org",
|
||||
});
|
||||
|
||||
// Set a non-httpOnly hint cookie so the landing page can detect login state.
|
||||
// In production this is handled server-side on .useautumn.com domain.
|
||||
if (window.location.hostname === "localhost") {
|
||||
if (data?.user) {
|
||||
document.cookie =
|
||||
"logged_in_hint=1; path=/; max-age=604800; SameSite=Lax";
|
||||
} else {
|
||||
document.cookie = "logged_in_hint=; path=/; max-age=0; SameSite=Lax";
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [data]);
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user