2.8 KB101 lines
Blame
1"use client";
2
3import { useEffect, useRef, useState } from "react";
4import { GroveLogo } from "@/app/components/grove-logo";
5import { useTheme } from "@/lib/theme";
6
7export function LandingPage() {
8 const [islDomain, setIslDomain] = useState("");
9 const { theme } = useTheme();
10 const islRef = useRef<HTMLIFrameElement>(null);
11
12 useEffect(() => {
13 const host = window.location.hostname;
14 if (host !== "localhost" && !host.match(/^\d/)) {
15 setIslDomain("https://isl.grove.host");
16 }
17 }, []);
18
19 // Send theme changes to ISL iframe via postMessage
20 useEffect(() => {
21 if (islRef.current?.contentWindow) {
22 islRef.current.contentWindow.postMessage({ type: "theme", value: theme }, "*");
23 }
24 }, [theme]);
25
26 return (
27 <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
28 {/* Hero + Terminal + Features */}
29 <div style={{ maxWidth: "800px", margin: "0 auto", padding: "60px 24px 0", width: "100%" }}>
30
31 {/* Hero */}
32 <div style={{ textAlign: "center", marginBottom: "64px" }}>
33 <div style={{ display: "inline-block", marginBottom: "24px" }}>
34 <GroveLogo size={64} />
35 </div>
36 <h1
37 style={{
38 fontSize: "2rem",
39 fontWeight: 400,
40 color: "var(--text-primary)",
41 marginBottom: "12px",
42 }}
43 >
44 Source control, self-hosted
45 </h1>
46 <p
47 style={{
48 fontSize: "1rem",
49 color: "var(--text-muted)",
50 maxWidth: "480px",
51 margin: "0 auto 32px",
52 lineHeight: 1.6,
53 }}
54 >
55 Grove is a complete code hosting platform built on Sapling SCM and Mononoke.
56 Stacked diffs, interactive smartlog, CI pipelines — on your own infrastructure.
57 </p>
58 <a
59 href="/login"
60 style={{
61 display: "inline-block",
62 padding: "10px 24px",
63 backgroundColor: "var(--accent)",
64 color: "var(--accent-text)",
65 fontSize: "0.875rem",
66 textDecoration: "none",
67 }}
68 >
69 Get started
70 </a>
71 </div>
72
73 </div>{/* end centered wrapper */}
74
75 {/* ISL — fills remaining viewport */}
76 {islDomain && (
77 <section
78 style={{
79 padding: "24px",
80 }}
81 >
82 <iframe
83 ref={islRef}
84 src={`${islDomain}?theme=${theme}`}
85 style={{
86 width: "100%",
87 height: "calc(100vh - 3.5rem)",
88 border: "1px solid var(--border-subtle)",
89 display: "block",
90 }}
91 title="Interactive Smartlog"
92 onLoad={() => {
93 islRef.current?.contentWindow?.postMessage({ type: "theme", value: theme }, "*");
94 }}
95 />
96 </section>
97 )}
98 </div>
99 );
100}
101