feat(home): route signed-in users and refresh landing page

This commit is contained in:
2026-11-06 12:50:23 +08:00
parent 86b5a4e9e4
commit 45e78f2e43
3 changed files with 262 additions and 340 deletions
+24 -340
View File
@@ -1,342 +1,26 @@
"use client";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import LandingPage from "@/components/landing-page";
import Link from "next/link";
import { useState } from "react";
import { ArrowUpRight, ArrowRight, Plus, Minus } from "lucide-react";
import { Brand } from "@/components/brand";
import { Button } from "@/components/ui/button";
const scenes = [
"收藏生活的切片",
"遇见新的工作方法",
"记下突然出现的灵感",
"给想法一点自由",
"做一件属于你的作品",
];
export default function Home() {
const [faq, setFaq] = useState<number | null>(0);
return (
<div className="landing">
<header className="site-nav">
<Brand />
<nav aria-label="主导航">
<a href="#tools">创作工具</a>
<a href="#ideas">知识与灵感</a>
<a href="#workflow">工作方式</a>
</nav>
<div className="nav-actions">
<Link href="/login">登录</Link>
<Button asChild>
<Link href="/login">
进入工作台 <ArrowUpRight size={15} />
</Link>
</Button>
</div>
</header>
<main>
<section className="hero container">
<div className="eyebrow">
<span className="status-dot" /> A SPACE FOR HUMAN IDEAS & AGENTS
</div>
<h1>
想法不该停在对话里。
<br />
让灵感,<span>有形。</span>
<svg
className="hero-stroke"
viewBox="0 0 230 18"
aria-hidden="true"
>
<path
d="M5 13 Q100 0 225 9"
fill="none"
stroke="currentColor"
strokeWidth="5"
strokeLinecap="round"
/>
</svg>
</h1>
<p className="hero-copy">
从一闪而过的念头,到值得分享的作品。
<br />
在一张画布上,把你的创作继续下去。
</p>
<div className="hero-actions">
<Button asChild size="lg">
<Link href="/login">
开始创作 <ArrowUpRight size={18} />
</Link>
</Button>
<a className="text-link" href="#space">
探索你的创作空间 <ArrowRight size={16} />
</a>
</div>
<div className="people-row">
{scenes.map((s, i) => (
<figure key={s}>
<div className="person-slot">
<img
src={"/assets/landingcontext-imgFrame" + (i + 1) + ".svg"}
width="200"
height="220"
alt={s}
/>
</div>
<figcaption>
<span>0{i + 1}</span>
{s}
</figcaption>
</figure>
))}
</div>
<div className="hero-footnote">
<span>COLLECT. CONNECT. CREATE.</span>
<span>给好奇心一点空间 ↓</span>
</div>
</section>
<section id="space" className="space-section">
<div className="container">
<div className="section-heading">
<div>
<div className="eyebrow">YOUR IDEAS, ALL TOGETHER</div>
<h2>
一个念头,
<br />
可以去很远。
</h2>
</div>
<p>
笔记、参考、还没想好的方向。
<br />
放在一起,看见它们之间的新可能。
</p>
</div>
<div className="product-preview">
<div className="preview-sidebar">
<Brand />
<p>
个人空间 <span>⌄</span>
</p>
<div className="preview-active">▦ 城市清晨</div>
<div>▧ 灵感收集</div>
<div>+ 新建画布</div>
<small>你的下一件作品,从这里开始。</small>
</div>
<div className="preview-canvas">
<div className="preview-bar">
☀ 城市清晨 <span>↗ 分享</span>
</div>
<div className="preview-note">
<small>01 / THE IDEA</small>
<h3>
把日常,
<br />
拍成一场电影。
</h3>
<p>
一束光、一段声音、
<br />
一个值得留下的瞬间。
</p>
</div>
<div className="preview-art">
<div className="light-shape" />
<span>光的形状</span>
</div>
<div className="preview-sticky">
慢一点。
<br />
让生活里的细节
<br />
成为下一次灵感。<span>✳</span>
</div>
<svg
viewBox="0 0 800 500"
preserveAspectRatio="none"
className="preview-connect"
aria-hidden="true"
>
<path
d="M290 235 C420 235 310 360 480 360"
fill="none"
stroke="#a98b72"
strokeWidth="1.5"
strokeDasharray="5 5"
/>
</svg>
<div className="preview-tools">↖ ✋ T ▧ □ ↗ +</div>
</div>
</div>
</div>
</section>
<section id="tools" className="tools-section container">
<div className="section-heading">
<div>
<div className="eyebrow">TWO TOOLS. ONE CREATIVE FLOW.</div>
<h2>
给不同的想法,
<br />
恰好的空间。
</h2>
</div>
<p>
从整理思路,到亲手完成作品。
<br />
每一步,都有你的空间。
</p>
</div>
<div className="tool-grid">
<article className="tool-card">
<div className="tool-meta">
01 / GRAPHIC <ArrowUpRight size={20} />
</div>
<div className="type-art">
MAKE
<br />
ROOM<span>for ideas.</span>
<i>✳</i>
</div>
<h3>把灵感排成作品。</h3>
<p>
让文字、图形与图片自由编排。打磨每个细节,留下属于你的表达。
</p>
<Link href="/login" className="text-link">
打开图形编辑器 <ArrowRight size={16} />
</Link>
</article>
<article className="tool-card">
<div className="tool-meta">
02 / INFINITE CANVAS <ArrowUpRight size={20} />
</div>
<div className="canvas-art">
<span>一个念头</span>
<i>⤳</i>
<span>一张参考</span>
<b>新的可能 ✧</b>
</div>
<h3>让思路,自由生长。</h3>
<p>
把笔记、参考图与提示词连成线索。在无限画布上,找到下一次创作的方向。
</p>
<Link href="/login" className="text-link">
打开无限画布 <ArrowRight size={16} />
</Link>
</article>
</div>
</section>
<section id="ideas" className="ideas-section">
<div className="container">
<div className="eyebrow">GOOD IDEAS DESERVE GOOD COMPANY</div>
<h2>
不必每一次,
<br />
都从空白开始。
</h2>
<div className="idea-grid">
{[
["留住一闪而过", "一句念头、一张参考图。先留下,再慢慢展开。"],
["让线索相遇", "把不同的灵感放上画布,用连接看见新的可能。"],
["把创作继续下去", "用熟悉的方法探索,再亲手调整细节。"],
].map(([title, copy], i) => (
<article key={title}>
<img
src={"/assets/landingcontext-imgFrame" + (i + 6) + ".svg"}
width="140"
height="110"
alt=""
/>
<h3>{title}</h3>
<p>{copy}</p>
</article>
))}
</div>
</div>
</section>
<section id="workflow" className="workflow container">
<div>
<div className="eyebrow">YOUR AGENT. YOUR WORKFLOW.</div>
<h2>
熟悉的工作方式。
<br />
新的创作可能。
</h2>
<p>
从一个小小的起点出发,让工具跟上你的想法。
<br />
整理、连接、亲手打磨,把创作继续下去。
</p>
<Link href="/login" className="text-link">
进入创作空间 <ArrowUpRight size={17} />
</Link>
</div>
<ol>
{[
["找到起点", "留住一个念头,或者从一张空白画布开始。"],
["连接工作方式", "把相关的笔记与参考放在一起。"],
["亲手打磨,保存作品", "调整细节,让想法成为自己的表达。"],
].map(([t, c], i) => (
<li key={t}>
<span>0{i + 1}</span>
<div>
<h3>{t}</h3>
<p>{c}</p>
</div>
</li>
))}
</ol>
</section>
<section className="faq container">
<div className="eyebrow">A FEW THINGS TO KNOW</div>
<h2>开始之前,你也许想知道。</h2>
{[
[
"我可以在这里做什么?",
"收集灵感、整理笔记、在画布上连接想法,逐步把零散的线索变成作品。",
],
[
"需要先想好完整的作品吗?",
"不用。可以从一段文字、一张参考或一个还没有想清楚的念头开始。",
],
[
"我的内容会自动公开吗?",
"你的工作空间需要登录访问。分享内容前,请确认工作空间的成员与权限设置。",
],
].map(([q, a], i) => (
<div className="faq-item" key={q}>
<button
aria-expanded={faq === i}
onClick={() => setFaq(faq === i ? null : i)}
>
{q}
{faq === i ? <Minus size={17} /> : <Plus size={17} />}
</button>
{faq === i && <p>{a}</p>}
</div>
))}
</section>
<section className="closing">
<div className="eyebrow">YOUR NEXT IDEA STARTS HERE</div>
<h2>
给下一个念头,
<br />
留一个起点。
</h2>
<p>不用想好全部。带着一点好奇,先开始。</p>
<Button asChild size="lg">
<Link href="/login">
进入你的工作台 <ArrowUpRight size={18} />
</Link>
</Button>
<span className="closing-star">✳</span>
</section>
</main>
<footer className="site-footer">
<Brand />
<p>给想法留白,给创作空间。</p>
<a href="#workflow">
工作方式 <ArrowUpRight size={14} />
</a>
<span>© {new Date().getFullYear()} Endoleap</span>
</footer>
</div>
);
export default async function Home() {
const session = (await cookies()).get("foundry_session")?.value;
let authenticated = false;
if (session) {
const origin = process.env.FOUNDRY_API_ORIGIN || "https://api.foundry.entroia.com";
const project = process.env.NEXT_PUBLIC_FOUNDRY_PROJECT || "endoleap";
try {
const response = await fetch(`${origin}/projects/${encodeURIComponent(project)}/profile`, {
headers: { Authorization: `Bearer ${session}` },
cache: "no-store",
redirect: "manual",
signal: AbortSignal.timeout(15000),
});
authenticated = response.ok;
await response.body?.cancel();
} catch {
// An unverified session must not hide the public landing page.
}
}
if (authenticated) redirect("/dashboard");
return <LandingPage />;
}