eny.space Landingpage
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(hero): add hero section

+181 -2
+29
app/components/button-link.tsx
··· 1 + import Link from "next/link"; 2 + import { cn } from "@/actions/lib/utils"; 3 + 4 + interface ButtonLinkProps { 5 + href: string; 6 + children: React.ReactNode; 7 + className?: string; 8 + endIcon?: React.ReactNode; 9 + } 10 + 11 + export function ButtonLink({ 12 + href, 13 + children, 14 + className, 15 + endIcon, 16 + }: ButtonLinkProps) { 17 + return ( 18 + <Link 19 + href={href} 20 + className={cn( 21 + "inline-flex h-11 items-center justify-center gap-2 rounded-full px-5 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2", 22 + className 23 + )} 24 + > 25 + {children} 26 + {endIcon} 27 + </Link> 28 + ); 29 + }
+13
app/components/heading.tsx
··· 1 + import { cn } from "@/actions/lib/utils"; 2 + 3 + type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; 4 + 5 + interface HeadingProps { 6 + as?: HeadingLevel; 7 + children: React.ReactNode; 8 + className?: string; 9 + } 10 + 11 + export function Heading({ as: Tag = "h1", children, className }: HeadingProps) { 12 + return <Tag className={cn(className)}>{children}</Tag>; 13 + }
+36
app/components/hero/hero-background.tsx
··· 1 + import Image from "next/image"; 2 + 3 + export function HeroBackground() { 4 + return ( 5 + <div 6 + className="absolute inset-0 -z-10 bg-neutral-950" 7 + aria-hidden 8 + > 9 + {/* Gradient from dark top to warm orange-yellow bottom */} 10 + <div 11 + className="absolute inset-0 opacity-90" 12 + style={{ 13 + background: 14 + "linear-gradient(180deg, transparent 0%, transparent 45%, oklch(0.75 0.12 75 / 0.4) 85%, oklch(0.8 0.14 85 / 0.6) 100%)", 15 + }} 16 + /> 17 + {/* Subtle grain overlay */} 18 + <div 19 + className="absolute inset-0 opacity-[0.03] mix-blend-overlay" 20 + style={{ 21 + backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E")`, 22 + }} 23 + /> 24 + {/* Large decorative logo - subtle, upper center */} 25 + <div className="absolute left-1/2 top-[20%] -translate-x-1/2 opacity-20"> 26 + <Image 27 + src="/logo.svg" 28 + alt="" 29 + width={480} 30 + height={480} 31 + className="shrink-0" 32 + /> 33 + </div> 34 + </div> 35 + ); 36 + }
+38
app/components/hero/hero-left.tsx
··· 1 + import { ButtonLink } from "@/components/button-link"; 2 + import { Heading } from "@/components/heading"; 3 + import { Paragraph } from "@/components/paragraph"; 4 + import { ArrowUpRightIcon } from "lucide-react"; 5 + 6 + export function HeroLeft() { 7 + return ( 8 + <div className="flex max-w-xl flex-col gap-6"> 9 + <Heading 10 + as="h1" 11 + className="text-4xl leading-tight tracking-tight text-white sm:text-5xl md:text-6xl" 12 + > 13 + Lorem ipsum dolor sit amet 14 + </Heading> 15 + <Paragraph className="text-lg text-white/90 sm:text-xl"> 16 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod 17 + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim 18 + veniam. 19 + </Paragraph> 20 + <div className="flex flex-wrap gap-3"> 21 + <ButtonLink 22 + href="/signup" 23 + className="border border-white/80 bg-transparent uppercase tracking-wide text-white hover:bg-white/10 hover:border-white focus-visible:ring-white/50" 24 + endIcon={<ArrowUpRightIcon className="size-4" aria-hidden />} 25 + > 26 + Button 1 27 + </ButtonLink> 28 + <ButtonLink 29 + href="/dashboard" 30 + className="border border-white/80 bg-transparent uppercase tracking-wide text-white hover:bg-white/10 hover:border-white focus-visible:ring-white/50" 31 + endIcon={<ArrowUpRightIcon className="size-4" aria-hidden />} 32 + > 33 + Button 2 34 + </ButtonLink> 35 + </div> 36 + </div> 37 + ); 38 + }
+34
app/components/hero/hero-right.tsx
··· 1 + import Link from "next/link"; 2 + import { ChevronDownIcon } from "lucide-react"; 3 + 4 + const navItems = [ 5 + { label: "Key features", href: "/#features" }, 6 + { label: "Build with eny.space", href: "/#build" }, 7 + { label: "Latest news", href: "/#news" }, 8 + ]; 9 + 10 + export function HeroRight() { 11 + return ( 12 + <nav className="flex flex-col gap-1"> 13 + <Link 14 + href="/#discover" 15 + className="border-b border-white/60 pb-1 text-sm font-medium uppercase tracking-wide text-white hover:border-white hover:text-white" 16 + > 17 + /// Discover eny.space 18 + </Link> 19 + <ul className="mt-4 flex flex-col gap-3"> 20 + {navItems.map((item) => ( 21 + <li key={item.href}> 22 + <Link 23 + href={item.href} 24 + className="inline-flex items-center gap-2 text-sm font-medium uppercase tracking-wide text-white/90 transition-colors hover:text-white" 25 + > 26 + {item.label} 27 + <ChevronDownIcon className="size-4" aria-hidden /> 28 + </Link> 29 + </li> 30 + ))} 31 + </ul> 32 + </nav> 33 + ); 34 + }
+15
app/components/hero/hero.tsx
··· 1 + import { HeroBackground } from "./hero-background"; 2 + import { HeroLeft } from "./hero-left"; 3 + import { HeroRight } from "./hero-right"; 4 + 5 + export function Hero() { 6 + return ( 7 + <section className="relative flex min-h-[calc(100vh-3.5rem)] w-full flex-col justify-end overflow-hidden px-4 pb-12 pt-16 sm:px-6 sm:pt-24"> 8 + <HeroBackground /> 9 + <div className="mx-auto grid w-full max-w-7xl gap-12 md:grid-cols-[1fr_auto] md:items-center md:gap-16"> 10 + <HeroLeft /> 11 + <HeroRight /> 12 + </div> 13 + </section> 14 + ); 15 + }
+4
app/components/hero/index.ts
··· 1 + export { Hero } from "./hero"; 2 + export { HeroBackground } from "./hero-background"; 3 + export { HeroLeft } from "./hero-left"; 4 + export { HeroRight } from "./hero-right";
+10
app/components/paragraph.tsx
··· 1 + import { cn } from "@/actions/lib/utils"; 2 + 3 + interface ParagraphProps { 4 + children: React.ReactNode; 5 + className?: string; 6 + } 7 + 8 + export function Paragraph({ children, className }: ParagraphProps) { 9 + return <p className={cn(className)}>{children}</p>; 10 + }
+2 -2
app/page.tsx
··· 1 - import { ComponentExample } from "@/actions/components/component-example"; 1 + import { Hero } from "@/components/hero/hero"; 2 2 3 3 export default function Page() { 4 - return <ComponentExample />; 4 + return <Hero />; 5 5 }