mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-27 20:20:07 -04:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b27b4854c | ||
|
|
395a4a3644 |
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import Landing from "../pages/landing";
|
||||
import Download from "../pages/download";
|
||||
import Navbar from "../components/navbar";
|
||||
import Footer from "../components/footer";
|
||||
import Landing2 from "../pages/landing2";
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
@@ -10,7 +10,7 @@ export function App() {
|
||||
<Navbar />
|
||||
|
||||
<Routes>
|
||||
<Route path="/" element={<Landing />} />
|
||||
<Route path="/" element={<Landing2 />} />
|
||||
<Route path="/download" element={<Download />} />
|
||||
</Routes>
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
import { faDiscord } from "@fortawesome/free-brands-svg-icons";
|
||||
import { SOCIAL_LINKS } from "../../config/links";
|
||||
|
||||
interface DiscordButtonProps {
|
||||
className?: string;
|
||||
small?: boolean;
|
||||
}
|
||||
|
||||
export const DiscordButton = ({
|
||||
className = "",
|
||||
small = false,
|
||||
}: DiscordButtonProps) => {
|
||||
const sizeClasses = small
|
||||
? "px-4 py-2 text-md rounded-xl"
|
||||
: "text-lg px-4 py-2 md:px-8 md:py-4 md:text-2xl rounded-2xl";
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={`relative z-10 ${sizeClasses} font-bold transition-all duration-300 shadow-lg hover:shadow-blue-500/25 ${className}`}
|
||||
icon={faDiscord}
|
||||
as="link"
|
||||
href={SOCIAL_LINKS.DISCORD}
|
||||
target="_blank"
|
||||
>
|
||||
Join Discord
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./discord-button";
|
||||
@@ -1,18 +1,15 @@
|
||||
import {
|
||||
Disclosure,
|
||||
DisclosureButton,
|
||||
DisclosurePanel,
|
||||
} from "@headlessui/react";
|
||||
import { Disclosure, DisclosureButton } from "@headlessui/react";
|
||||
import { faBars } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
// import { Button } from "@storyteller/ui-button";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useEffect, useState } from "react";
|
||||
import { DiscordButton } from "../discord-button";
|
||||
|
||||
const navigation = [
|
||||
{ name: "Home", href: "/", current: true },
|
||||
{ name: "Download", href: "/download", current: false },
|
||||
];
|
||||
// const navigation = [
|
||||
// { name: "Home", href: "/", current: true },
|
||||
// { name: "Download", href: "/download", current: false },
|
||||
// ];
|
||||
|
||||
export default function Navbar() {
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
@@ -30,11 +27,13 @@ export default function Navbar() {
|
||||
<Disclosure
|
||||
as="nav"
|
||||
className={twMerge(
|
||||
"z-20 fixed top-0 left-0 w-full transition-colors duration-200",
|
||||
scrolled ? "bg-[#1b1b1f]/70 backdrop-blur-lg" : "bg-transparent"
|
||||
"z-20 fixed top-0 left-0 w-full transition-colors duration-200 bg-transparent",
|
||||
scrolled
|
||||
? "bg-[#1b1b1f]/70 backdrop-blur-lg lg:bg-transparent lg:backdrop-blur-none"
|
||||
: "bg-transparent"
|
||||
)}
|
||||
>
|
||||
<div className="mx-auto max-w-[1920px] sm:px-6 lg:px-8 px-6 md:px-16 xl:px-32">
|
||||
<div className="mx-auto max-w-screen sm:px-6 lg:px-8 px-6 md:px-16 xl:px-4">
|
||||
<div className="flex h-16 justify-between">
|
||||
<div className="flex">
|
||||
<div className="flex shrink-0 items-center">
|
||||
@@ -46,7 +45,7 @@ export default function Navbar() {
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div className="hidden md:ml-7 md:flex md:items-center md:space-x-3">
|
||||
{/* <div className="hidden md:ml-7 md:flex md:items-center md:space-x-3">
|
||||
{navigation.map((item) => (
|
||||
<a
|
||||
key={item.name}
|
||||
@@ -62,27 +61,24 @@ export default function Navbar() {
|
||||
{item.name}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="hidden md:ml-4 md:flex md:shrink-0 md:items-center">
|
||||
<Button as="link" href="/download">
|
||||
{/* <Button as="link" href="/download">
|
||||
Download
|
||||
</Button>
|
||||
</Button> */}
|
||||
<DiscordButton small />
|
||||
</div>
|
||||
<div className="mr-2 -ml-2 flex items-center md:hidden">
|
||||
<div className="-ml-2 flex items-center md:hidden">
|
||||
{/* Mobile menu button */}
|
||||
<DisclosureButton className="group relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:ring-2 focus:ring-white focus:outline-hidden focus:ring-inset">
|
||||
<span className="absolute -inset-0.5" />
|
||||
<span className="sr-only">Open main menu</span>
|
||||
<FontAwesomeIcon icon={faBars} />
|
||||
</DisclosureButton>
|
||||
<DiscordButton className="text-sm" small />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DisclosurePanel className="md:hidden">
|
||||
{/* <DisclosurePanel className="md:hidden">
|
||||
<div className="space-y-1 px-2 pt-2 pb-3 sm:px-3">
|
||||
{navigation.map((item) => (
|
||||
<DisclosureButton
|
||||
@@ -101,7 +97,7 @@ export default function Navbar() {
|
||||
</DisclosureButton>
|
||||
))}
|
||||
</div>
|
||||
</DisclosurePanel>
|
||||
</DisclosurePanel> */}
|
||||
</Disclosure>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./landing";
|
||||
export * from "./landing2";
|
||||
export * from "./download";
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./landing2";
|
||||
@@ -0,0 +1,238 @@
|
||||
import { DiscordButton } from "../../components/discord-button";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
const fadeUpVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.6,
|
||||
delay: 0.2,
|
||||
ease: "easeOut",
|
||||
staggerChildren: 0.1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Landing = () => {
|
||||
const videos = [
|
||||
{
|
||||
src: "https://www.youtube.com/embed/H4NFXGMuwpY?si=U2_m5Ic1YBn6176D",
|
||||
},
|
||||
{
|
||||
src: "https://www.youtube.com/embed/pGn-1BKo3nY?si=q4dm0ICb6wF1JW8N",
|
||||
},
|
||||
{
|
||||
src: "https://www.youtube.com/embed/7x7IZkHiGD8?si=tL8nK4CULigpfHQR",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="relative min-h-screen bg-[#101014] text-white bg-dots">
|
||||
<div className="dotted-pattern absolute inset-0 z-[0] opacity-50" />
|
||||
{/* Hero Section */}
|
||||
<div className="relative flex overflow-hidden xl:items-center xl:pt-0 mb-0">
|
||||
<motion.div
|
||||
className="w-full flex flex-col items-center justify-center text-center pt-36 px-10"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<motion.div className="relative" variants={fadeUpVariants}>
|
||||
<h1 className="relative mb-6 md:mb-10 font-extrabold text-4xl sm:text-[3rem] md:text-[4rem] lg:text-[6rem] !leading-none">
|
||||
<span className="text-primary">“</span>
|
||||
Is this really AI?
|
||||
<span className="text-primary">”</span>
|
||||
</h1>
|
||||
<span className="absolute -right-5 bottom-1 md:-right-14 md:bottom-14 text-xl md:text-3xl font-bold opacity-40 italic">
|
||||
— You
|
||||
</span>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Hero Section */}
|
||||
<div className="relative z-10 mx-auto max-w-[100rem] px-4 md:px-16 lg:px-12 xl:px-32 lg:mb-32">
|
||||
<motion.div
|
||||
className="items-center gap-16 mb-12 p-4 bg-white/10 backdrop-blur-md rounded-[40px]"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="rounded-[24px] overflow-hidden bg-[#1C1C20]">
|
||||
<video
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
className="w-full aspect-[16/9] object-cover"
|
||||
>
|
||||
<source src="/videos/hero-video.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="flex justify-center"
|
||||
variants={fadeUpVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<DiscordButton />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="overflow-hidden py-24 sm:py-32">
|
||||
<motion.div
|
||||
className="mx-auto max-w-[88rem] md:px-6 lg:px-8"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="grid grid-cols-1 gap-20 lg:grid-cols-2 lg:items-center">
|
||||
<motion.div
|
||||
className="px-6 lg:px-0 lg:pt-4 lg:pr-4"
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="max-w-2xl lg:mx-0 mb-10 md:mb-16">
|
||||
<h2 className="relative font-extrabold text-4xl md:text-5xl lg:text-6xl xl:text-[4.8rem] !leading-tight">
|
||||
Our tool lets you design, control, and achieve{" "}
|
||||
<span className="text-primary">great consistency.</span>
|
||||
</h2>
|
||||
</div>
|
||||
<DiscordButton />
|
||||
</motion.div>
|
||||
<div className="sm:px-6 lg:px-0">
|
||||
<div className="relative isolate overflow-hidden bg-indigo-500 sm:mx-auto sm:max-w-2xl sm:rounded-3xl sm:pr-0 lg:mx-0 lg:max-w-none">
|
||||
<div className="mx-auto max-w-2xl sm:mx-0 sm:max-w-none border-[16px] border-white/10 rounded-3xl overflow-hidden">
|
||||
<video
|
||||
src="/videos/artcraft-3d-demo.mp4"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
className="aspect-square w-full max-w-none rounded-tl-xl bg-gray-800 ring-1 ring-white/10 object-cover h-full rounded-lg overflow-hidden"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="overflow-hidden md:py-24 sm:py-32">
|
||||
<motion.div
|
||||
className="mx-auto max-w-[88rem] md:px-6 lg:px-8"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="grid grid-cols-1 gap-20 lg:grid-cols-2 lg:items-center">
|
||||
<div className="sm:px-6 lg:px-0 order-2 lg:order-1">
|
||||
<motion.div
|
||||
className="relative isolate overflow-hidden bg-indigo-500 sm:mx-auto sm:max-w-2xl sm:rounded-3xl sm:pr-0 lg:mx-0 lg:max-w-none"
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="mx-auto max-w-2xl sm:mx-0 sm:max-w-none border-[16px] border-white/10 rounded-3xl overflow-hidden">
|
||||
<motion.video
|
||||
src="/videos/artcraft-canvas-demo.mp4"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
className="aspect-square w-full max-w-none rounded-tl-xl bg-gray-800 ring-1 ring-white/10 object-cover h-full rounded-lg overflow-hidden"
|
||||
variants={fadeUpVariants}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
<motion.div
|
||||
className="px-6 lg:px-0 lg:pt-4 lg:pr-4 order-1 lg:order-2"
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className=" max-w-2xl lg:mx-0 mb-10 md:mb-16">
|
||||
<h2 className="relative font-extrabold text-4xl md:text-5xl lg:text-6xl xl:text-[4.8rem] !leading-tight">
|
||||
<span className="text-primary">Patented</span> Brain to Art
|
||||
Interface
|
||||
</h2>
|
||||
</div>
|
||||
<DiscordButton />
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="relative z-10 mx-auto max-w-screen px-4 py-32 sm:px-24 lg:px-32">
|
||||
{/* Videos Section */}
|
||||
<motion.div
|
||||
className="space-y-12"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="text-center">
|
||||
<h1 className="md:mb-16 text-4xl md:text-7xl font-extrabold">
|
||||
Made using{" "}
|
||||
<span className="relative after:absolute after:bottom-0 after:left-0 after:w-full after:h-[5px] md:after:h-[12px] after:bg-primary/60 after:mb-1">
|
||||
ArtCraft
|
||||
</span>
|
||||
</h1>
|
||||
{/* <p className="text-lg text-gray-300 max-w-2xl mx-auto">
|
||||
See examples of artwork created using ArtCraft.
|
||||
</p> */}
|
||||
</div>
|
||||
<div className="grid gap-8 xl:grid-cols-3">
|
||||
{videos.map((video, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
className="group relative rounded-2xl bg-white/10 backdrop-blur-md p-1.5 transition-all duration-300 hover:bg-white/20 hover:scale-[1.02] hover:shadow-2xl hover:shadow-primary/20"
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<div className="aspect-video overflow-hidden rounded-xl">
|
||||
<iframe
|
||||
width="100%"
|
||||
height="100%"
|
||||
src={video.src}
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
referrerPolicy="strict-origin-when-cross-origin"
|
||||
allowFullScreen
|
||||
className="rounded-xl transition-transform duration-300 group-hover:scale-[1.02]"
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute inset-0 rounded-2xl border border-white/10 group-hover:border-white/20 transition-colors duration-300 pointer-events-none" />
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="relative z-10 mx-auto max-w-[1920px] px-4 md:pt-32 md:pb-56 sm:px-24 lg:px-32">
|
||||
{/* Discord CTA Section */}
|
||||
<motion.div
|
||||
className="flex flex-col items-center justify-center text-center p-12 py-20 rounded-[40px] bg-primary/30 backdrop-blur-md border-[6px] border-primary/60"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeUpVariants}
|
||||
>
|
||||
<h2 className="relative mb-12 font-extrabold text-4xl lg:text-6xl max-w-3xl !leading-tight">
|
||||
Why haven't you joined our Discord yet?
|
||||
</h2>
|
||||
{/* <p className="text-lg text-gray-400 mb-8 max-w-2xl">
|
||||
Connect with other creators, share your work, get feedback, and stay
|
||||
updated with the latest features and updates.
|
||||
</p> */}
|
||||
<DiscordButton />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Landing;
|
||||
@@ -51,6 +51,9 @@
|
||||
},
|
||||
{
|
||||
"path": "../../libs/tauri-utils/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../editor3d"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
{
|
||||
"path": "../../libs/tauri-utils"
|
||||
},
|
||||
{
|
||||
"path": "../editor3d"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
|
||||
Generated
+40
@@ -16,6 +16,7 @@
|
||||
"@headlessui/react": "^2.2.2",
|
||||
"@preact/signals-react": "^3.0.1",
|
||||
"@remix-run/serve": "^2.15.0",
|
||||
"framer-motion": "^12.11.0",
|
||||
"pnpm": "^10.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
@@ -18610,6 +18611,32 @@
|
||||
"url": "https://github.com/sponsors/rawify"
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "12.11.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.11.0.tgz",
|
||||
"integrity": "sha512-BaBPmkhaC2l0n619Kt1nQaxSdUdyyz5V1Z7EKJ1CcraOTZitgVx0RTbL8lmg2XesaFi6o8MPBIhkWDIvzDpGaQ==",
|
||||
"dependencies": {
|
||||
"motion-dom": "^12.11.0",
|
||||
"motion-utils": "^12.9.4",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/is-prop-valid": "*",
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/is-prop-valid": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
@@ -22987,6 +23014,19 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-dom": {
|
||||
"version": "12.11.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.11.0.tgz",
|
||||
"integrity": "sha512-CItkGYJenn5ZsbzTX0D9mE0UWdjdd9r535FrxEXhzR8Kwa9I2dLr1uhEJgQPWbgaIJ6i0sNFnf2T9NvVDWQVBw==",
|
||||
"dependencies": {
|
||||
"motion-utils": "^12.9.4"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-utils": {
|
||||
"version": "12.9.4",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.9.4.tgz",
|
||||
"integrity": "sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg=="
|
||||
},
|
||||
"node_modules/mri": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"@headlessui/react": "^2.2.2",
|
||||
"@preact/signals-react": "^3.0.1",
|
||||
"@remix-run/serve": "^2.15.0",
|
||||
"framer-motion": "^12.11.0",
|
||||
"pnpm": "^10.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
|
||||
Reference in New Issue
Block a user