|
1 | | -"use client" |
2 | | - |
3 | | -import { useMemo, useState } from "react" |
| 1 | +import Link from "next/link" |
4 | 2 |
|
| 3 | +import { AnimatedBackground } from "@/components/AnimatedBackground" |
| 4 | +import { Hero } from "@/components/Hero" |
5 | 5 | import { Button } from "@/components/ui/button" |
6 | | -import { InstructionsWizard } from "@/components/instructions-wizard" |
7 | | -import { getHomeMainClasses } from "@/lib/utils" |
8 | | -import { getFormatLabel } from "@/lib/wizard-utils" |
9 | | -import { ANALYTICS_EVENTS } from "@/lib/analytics-events" |
10 | | -import { track } from "@/lib/mixpanel" |
11 | | -import type { FileOutputConfig } from "@/types/wizard" |
12 | 6 | import { Github } from "lucide-react" |
13 | | -import Link from "next/link" |
14 | | - |
15 | | -import Logo from "./../components/Logo" |
16 | | -import filesData from "@/data/files.json" |
17 | | - |
18 | | -export default function Home() { |
19 | | - const [showWizard, setShowWizard] = useState(false) |
20 | | - const [selectedFileId, setSelectedFileId] = useState<string | null>(null) |
21 | | - |
22 | | - const fileOptions = useMemo(() => { |
23 | | - return (filesData as FileOutputConfig[]).filter((file) => file.enabled !== false) |
24 | | - }, []) |
25 | | - |
26 | | - const handleFileCtaClick = (file: FileOutputConfig) => { |
27 | | - setSelectedFileId(file.id) |
28 | | - setShowWizard(true) |
29 | | - track(ANALYTICS_EVENTS.CREATE_INSTRUCTIONS_FILE, { |
30 | | - fileId: file.id, |
31 | | - fileLabel: file.label, |
32 | | - }) |
33 | | - } |
34 | | - |
35 | | - const handleWizardClose = () => { |
36 | | - setShowWizard(false) |
37 | | - setSelectedFileId(null) |
38 | | - } |
39 | 7 |
|
| 8 | +export default function LandingPage() { |
40 | 9 | return ( |
41 | | - <div className="min-h-screen bg-background text-foreground"> |
42 | | - {/* Top utility bar */} |
43 | | - <div className="absolute top-4 right-4 z-10"> |
44 | | - <Link href="https://github.com/spivx/devcontext" target="_blank"> |
45 | | - <Button variant="outline" size="sm"> |
46 | | - <Github className="mr-2 h-4 w-4" /> |
47 | | - GitHub |
48 | | - </Button> |
49 | | - </Link> |
| 10 | + <div className="relative min-h-screen overflow-hidden bg-background text-foreground"> |
| 11 | + <AnimatedBackground /> |
| 12 | + <div className="relative z-10 flex min-h-screen flex-col"> |
| 13 | + <header className="flex items-center justify-between px-6 py-6 lg:px-12 lg:py-8"> |
| 14 | + <Link href="/" className="text-lg font-semibold tracking-tight text-foreground md:text-xl"> |
| 15 | + DevContext |
| 16 | + </Link> |
| 17 | + <div className="flex items-center gap-3"> |
| 18 | + <Button asChild variant="ghost" size="sm" className="hidden sm:inline-flex"> |
| 19 | + <Link href="/new">Launch wizard</Link> |
| 20 | + </Button> |
| 21 | + <Button asChild variant="outline" size="sm"> |
| 22 | + <Link href="https://github.com/spivx/devcontext" rel="noreferrer" target="_blank"> |
| 23 | + <Github className="size-4" /> |
| 24 | + GitHub |
| 25 | + </Link> |
| 26 | + </Button> |
| 27 | + </div> |
| 28 | + </header> |
| 29 | + |
| 30 | + <main className="flex flex-1 flex-col"> |
| 31 | + <Hero /> |
| 32 | + </main> |
| 33 | + |
| 34 | + <footer className="px-6 pb-10 text-center text-xs text-muted-foreground lg:px-12"> |
| 35 | + Open-source and community built — keep shipping with more context than commits. |
| 36 | + </footer> |
50 | 37 | </div> |
51 | | - |
52 | | - {/* Hero Section */} |
53 | | - <main className={getHomeMainClasses(showWizard)}> |
54 | | - {showWizard && selectedFileId ? ( |
55 | | - <InstructionsWizard selectedFileId={selectedFileId} onClose={handleWizardClose} /> |
56 | | - ) : ( |
57 | | - <> |
58 | | - <div className="space-y-6"> |
59 | | - {/* Logo/Title */} |
60 | | - <Logo /> |
61 | | - |
62 | | - {/* Headline */} |
63 | | - <h1 className="max-w-4xl text-3xl font-bold"> |
64 | | - Assemble Tailored AI Coding Playbooks With a Guided Wizard |
65 | | - </h1> |
66 | | - |
67 | | - {/* Subheadline */} |
68 | | - <p className="max-w-xl text-lg leading-relaxed text-muted-foreground"> |
69 | | - Move from curated best practices to sharable files like Copilot instructions, Cursor rules, and agents.md playbooks in just a few guided steps. |
70 | | - </p> |
71 | | - |
72 | | - <p className="max-w-xl text-sm text-muted-foreground/80"> |
73 | | - Use the wizard to generate Copilot instruction files, agents files, comprehensive instruction sets, and Cursor rules without starting from a blank page. |
74 | | - </p> |
75 | | - |
76 | | - {/* File type CTAs */} |
77 | | - <div className="pt-6"> |
78 | | - <div className="grid gap-4 md:grid-cols-2"> |
79 | | - {fileOptions.map((file) => { |
80 | | - const formatLabel = getFormatLabel(file.format) |
81 | | - return ( |
82 | | - <button |
83 | | - key={file.id} |
84 | | - type="button" |
85 | | - className="group relative flex w-full flex-col items-start gap-3 rounded-3xl border border-border/60 bg-card/80 p-6 text-left shadow-sm ring-offset-background transition-all hover:-translate-y-1 hover:border-primary/60 hover:shadow-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/80" |
86 | | - onClick={() => handleFileCtaClick(file)} |
87 | | - aria-label={`Create ${file.label}`} |
88 | | - > |
89 | | - <div className="flex items-center gap-2 rounded-full bg-secondary/60 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-secondary-foreground/80"> |
90 | | - <span className="inline-flex h-2 w-2 rounded-full bg-primary/70" aria-hidden /> |
91 | | - <span>Start with</span> |
92 | | - </div> |
93 | | - <div> |
94 | | - <p className="text-xl font-semibold text-foreground transition-colors group-hover:text-primary"> |
95 | | - {file.label} |
96 | | - </p> |
97 | | - {file.filename ? ( |
98 | | - <p className="mt-1 text-sm text-muted-foreground"> |
99 | | - {file.filename} |
100 | | - </p> |
101 | | - ) : null} |
102 | | - </div> |
103 | | - {formatLabel ? ( |
104 | | - <span className="inline-flex items-center gap-2 rounded-full bg-primary/10 px-3 py-1 text-xs font-medium text-primary"> |
105 | | - {formatLabel} format |
106 | | - </span> |
107 | | - ) : null} |
108 | | - <span className="pointer-events-none absolute right-6 top-6 text-primary/60 transition-transform group-hover:translate-x-1"> |
109 | | - → |
110 | | - </span> |
111 | | - </button> |
112 | | - ) |
113 | | - })} |
114 | | - </div> |
115 | | - </div> |
116 | | - </div> |
117 | | - </> |
118 | | - )} |
119 | | - </main> |
120 | | - |
121 | 38 | </div> |
122 | 39 | ) |
123 | 40 | } |
0 commit comments