diff --git a/frontend/apps/artcraft-website/_redirects b/frontend/apps/artcraft-website/_redirects index b982b3b1a5..4603f90b47 100644 --- a/frontend/apps/artcraft-website/_redirects +++ b/frontend/apps/artcraft-website/_redirects @@ -67,3 +67,7 @@ /password-reset /index.html 200 /password-reset/ /index.html 200 /password-reset/* /index.html 200 + +/seedance-2 /index.html 200 +/seedance-2/ /index.html 200 +/seedance-2/* /index.html 200 diff --git a/frontend/apps/artcraft-website/src/app/app.tsx b/frontend/apps/artcraft-website/src/app/app.tsx index 403c2e6ffc..49181831cf 100644 --- a/frontend/apps/artcraft-website/src/app/app.tsx +++ b/frontend/apps/artcraft-website/src/app/app.tsx @@ -4,6 +4,7 @@ import Media from "../pages/media"; import PressKit from "../pages/press-kit"; import Navbar from "../components/navbar"; import Landing2 from "../pages/landing2"; +import LandingSD2 from "../pages/landing-sd2"; import TutorialsPage from "../pages/tutorials"; import TutorialsArticle from "../pages/tutorials/article"; import FaqIndex from "../pages/faq/index"; @@ -25,6 +26,7 @@ export function App() { } /> + } /> } /> } /> } /> diff --git a/frontend/apps/artcraft-website/src/pages/landing-sd2/index.ts b/frontend/apps/artcraft-website/src/pages/landing-sd2/index.ts new file mode 100644 index 0000000000..35f9b5117e --- /dev/null +++ b/frontend/apps/artcraft-website/src/pages/landing-sd2/index.ts @@ -0,0 +1 @@ +export { default } from "./landing-sd2"; diff --git a/frontend/apps/artcraft-website/src/pages/landing-sd2/landing-sd2.tsx b/frontend/apps/artcraft-website/src/pages/landing-sd2/landing-sd2.tsx new file mode 100644 index 0000000000..dd9e999bd3 --- /dev/null +++ b/frontend/apps/artcraft-website/src/pages/landing-sd2/landing-sd2.tsx @@ -0,0 +1,840 @@ +import { DiscordButton } from "../../components/discord-button"; +import { Button } from "@storyteller/ui-button"; +import { isMobile } from "react-device-detect"; +import { faGithub } from "@fortawesome/free-brands-svg-icons"; +import { + faFilm, + faPaintBrush, + faCamera, + faMapMarkerAlt, + faCube, + faLayerGroup, + faUser, + faTools, + faShapes, + faEraser, +} from "@fortawesome/pro-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import Footer from "../../components/footer"; +import { useState, useRef, useEffect, useLayoutEffect } from "react"; +import gsap from "gsap"; +import { ScrollTrigger } from "gsap/ScrollTrigger"; +import ModelBadgeGrid from "../../components/model-badge-grid"; +import Seo from "../../components/seo"; + +import { OwnershipComparison } from "../../components/ownership-comparison/ownership-comparison"; +import { DownloadModal } from "../../components/download-modal"; + +import { UsersApi } from "@storyteller/api"; +import { LandingActionButtons } from "../../components/landing-action-buttons"; + +gsap.registerPlugin(ScrollTrigger); + +const HERO_VIMEO_URL = + "https://player.vimeo.com/video/1169289718?autoplay=1&muted=1&loop=1&background=0&byline=0&portrait=0&title=0"; + +const LandingSD2 = () => { + const videos = [ + { + src: "https://www.youtube.com/embed/oqoCWdOwr2U?si=ILMPk8hGHo9hP8RU", + }, + { + src: "https://www.youtube.com/embed/H4NFXGMuwpY?si=wPuQl5cJOu1v8MJu", + }, + { + src: "https://www.youtube.com/embed/7x7IZkHiGD8?si=tL8nK4CULigpfHQR", + }, + ]; + + const [activeFeature, setActiveFeature] = useState(0); + const [activeVideo, setActiveVideo] = useState(null); + const [showDownloadModal, setShowDownloadModal] = useState(false); + const [isLoggedIn, setIsLoggedIn] = useState(false); + + useEffect(() => { + const checkSession = async () => { + const api = new UsersApi(); + const response = await api.GetSession(); + if (response.success && response.data?.loggedIn) { + setIsLoggedIn(true); + } + }; + checkSession(); + }, []); + + const onDownloadClick = (e: React.MouseEvent) => { + if (isLoggedIn) { + return; + } + + setShowDownloadModal(true); + + localStorage.setItem("artcraft_download_initiated", "true"); + }; + + const features = [ + { + icon: faMapMarkerAlt, + title: "Image to Location", + description: + "Placing virtual actors into physical environments establishes single-location consistency. You can film multiple shots within a room without having things disappear.", + src: "/videos/features/WorldLabs_Demo_2.webm", + }, + { + icon: faCube, + title: "3D Image Compositing", + description: + "Use images (backdrops, foreground elements, props, etc.) in scenes with depth and blend them naturally together. Just a couple of images usually leads to great compositions.", + src: "/videos/features/Panel.webm", + }, + { + icon: faLayerGroup, + title: "2D Image Compositing", + description: + "Use images, background removal, layers, and simple drawing tools to precisely compose a scene.", + src: "/videos/features/Editor.webm", + }, + { + icon: faShapes, + title: "Image to 3D Mesh", + description: + "It's almost impossible to lay out complicated objects or block complicated scenes; turning images into 3D helps position elements exactingly and intentionally.", + src: "/videos/features/Make_3D.webm", + }, + { + icon: faTools, + title: "Mixed Asset Crafting", + description: + "You can use image cutouts, worlds, and simple 3D meshes all together to precisely and intentionally lay out your scenes.", + src: "/videos/features/Mixed.webm", + }, + { + icon: faUser, + title: "Character Posing", + description: + 'You can dynamically pose your characters to achieve the precise character, scene, and camera blocking before calling "action".', + src: "/videos/features/Pose_Second_Version.webm", + }, + { + icon: faEraser, + title: "Background Removal", + description: + "Instantly remove backgrounds from images to create assets for your scenes. Clean, precise, and ready for compositing.", + src: "/videos/features/Background.webm", + }, + ]; + + // Refs for GSAP animations + const mainRef = useRef(null); + const containerRef = useRef(null); + const featureRefs = useRef<(HTMLDivElement | null)[]>([]); + const cardRefs = useRef<(HTMLDivElement | null)[]>([]); + const mobileMediaRef = useRef(null); + const mobileDescRef = useRef(null); + + // GSAP ScrollTrigger setup for page animations + useLayoutEffect(() => { + const mm = gsap.matchMedia(); + const ctx = gsap.context(() => { + // Animate elements with data-animate attribute on scroll + // ONLY on non-mobile devices to ensure performance and prevent content loading issues + if (!isMobile) { + const elements = gsap.utils.toArray("[data-animate]"); + + gsap.set(elements, { autoAlpha: 0, y: 20 }); + + elements.forEach((el) => { + gsap.to(el, { + autoAlpha: 1, + y: 0, + duration: 0.8, + ease: "power1.out", + scrollTrigger: { + trigger: el, + start: "top 90%", + toggleActions: "play none none none", + }, + }); + }); + } + + // Feature section pinning and active state - Desktop Only (lg breakpoint) + mm.add("(min-width: 1024px)", () => { + ScrollTrigger.create({ + trigger: ".right-column", + start: "top top", + endTrigger: ".left-column", + end: "bottom bottom", + pin: true, + pinSpacing: false, + invalidateOnRefresh: true, + }); + + featureRefs.current.forEach((el, index) => { + if (!el) return; + ScrollTrigger.create({ + trigger: el, + start: "top 40%", + end: "bottom 40%", + onEnter: () => setActiveFeature(index), + onEnterBack: () => setActiveFeature(index), + }); + }); + }); + }, mainRef); + + return () => { + ctx.revert(); + mm.revert(); + }; + }, []); + + // GSAP animation for card stack (desktop feature images) + useEffect(() => { + cardRefs.current.forEach((card, index) => { + if (!card) return; + const isFuture = index > activeFeature; + const isPast = index < activeFeature; + + gsap.to(card, { + y: isFuture ? "110%" : "0%", + scale: isPast ? 0.9 : 1, + opacity: isPast ? 0.4 : 1, + duration: 0.5, + ease: "power3.out", + }); + }); + }, [activeFeature]); + + // GSAP animation for mobile media and description + useEffect(() => { + if (mobileMediaRef.current) { + gsap.fromTo( + mobileMediaRef.current, + { opacity: 0 }, + { opacity: 1, duration: 0.4, ease: "power2.out" }, + ); + } + if (mobileDescRef.current) { + gsap.fromTo( + mobileDescRef.current, + { opacity: 0, y: 10 }, + { opacity: 1, y: 0, duration: 0.3, ease: "power2.out" }, + ); + } + }, [activeFeature]); + + return ( +
+ + {/* Hero Section */} +
+ {/* Glowing Gradient Orb Background */} +
+
+
+ +
+
+ {/* Main Heading */} +

+ + Seedance 2.0 +
+ now in{" "} + + ArtCraft + +
+

+ + {/* Subtitle */} +

+ Generate jaw-dropping AI videos with Seedance 2.0 before + it’s available anywhere else. +

+ + {/* CTA Buttons */} +
+ + Buy Credits + Try Download +
+ + {/* Vimeo Video Embed */} +
+
+
+