feat(home): redesign homepage into refined full-screen hero flow
This commit is contained in:
@@ -82,6 +82,68 @@ export const translations = {
|
|||||||
learnMore: 'Learn More About Me',
|
learnMore: 'Learn More About Me',
|
||||||
toolbox: 'My Toolbox',
|
toolbox: 'My Toolbox',
|
||||||
},
|
},
|
||||||
|
home: {
|
||||||
|
hero: {
|
||||||
|
eyebrow: 'Personal Brand',
|
||||||
|
summary: 'I design and build reliable digital products with clear user value, strong engineering foundations, and practical AI integration.',
|
||||||
|
ctaPrimary: 'About Me',
|
||||||
|
ctaSecondary: 'Work With Me',
|
||||||
|
terminalStatus: 'Open to remote roles and project collaboration',
|
||||||
|
},
|
||||||
|
trust: {
|
||||||
|
item1: 'Remote Ready',
|
||||||
|
item2: 'Async Friendly Collaboration',
|
||||||
|
item3: 'Product + Engineering Mindset',
|
||||||
|
item4: 'Stable Delivery Rhythm',
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
item1: 'Focused on long-term product quality',
|
||||||
|
item2: 'Strong in TypeScript, React, and Node.js',
|
||||||
|
item3: 'Comfortable with AI-enabled product workflows',
|
||||||
|
item4: 'Available for freelance and full-time opportunities',
|
||||||
|
},
|
||||||
|
services: {
|
||||||
|
eyebrow: 'What I Deliver',
|
||||||
|
title: 'Services',
|
||||||
|
description: 'Practical technical support from strategy to execution.',
|
||||||
|
},
|
||||||
|
career: {
|
||||||
|
eyebrow: 'Career Snapshot',
|
||||||
|
title: 'Career Highlights',
|
||||||
|
description: 'Mock milestones for layout. Real details can be swapped in later.',
|
||||||
|
cta: 'View Full Resume',
|
||||||
|
card1: {
|
||||||
|
period: '2024 — Now',
|
||||||
|
title: 'AI Product Builder · Independent',
|
||||||
|
outcome: 'Built and iterated AI-first product concepts with fast prototyping and clear product direction.',
|
||||||
|
},
|
||||||
|
card2: {
|
||||||
|
period: '2021 — 2024',
|
||||||
|
title: 'Senior Frontend Engineer · Remote Team',
|
||||||
|
outcome: 'Led core front-end modules and improved team delivery efficiency through reusable architecture.',
|
||||||
|
},
|
||||||
|
card3: {
|
||||||
|
period: '2018 — 2021',
|
||||||
|
title: 'Full-stack Engineer · Growth Stage Startup',
|
||||||
|
outcome: 'Delivered multiple customer-facing features across web stack and supported stable product growth.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
featured: {
|
||||||
|
eyebrow: 'Featured Work',
|
||||||
|
title: 'Representative Project',
|
||||||
|
challenge: 'Challenge',
|
||||||
|
approach: 'Approach',
|
||||||
|
outcome: 'Outcome',
|
||||||
|
ctaPrimary: 'View Project',
|
||||||
|
ctaSecondary: 'See More Opportunities',
|
||||||
|
},
|
||||||
|
final: {
|
||||||
|
title: 'Open to Meaningful Work',
|
||||||
|
description: 'If you are building quality products and need reliable execution, I would love to connect.',
|
||||||
|
ctaPrimary: 'Know Me Better',
|
||||||
|
ctaSecondary: 'Start a Conversation',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
nav: {
|
nav: {
|
||||||
@@ -160,6 +222,68 @@ export const translations = {
|
|||||||
learnMore: '了解更多',
|
learnMore: '了解更多',
|
||||||
toolbox: '我的工具箱',
|
toolbox: '我的工具箱',
|
||||||
},
|
},
|
||||||
|
home: {
|
||||||
|
hero: {
|
||||||
|
eyebrow: '个人品牌',
|
||||||
|
summary: '我专注于打造可靠且有业务价值的数字产品,兼顾工程质量、产品思维与 AI 实践落地。',
|
||||||
|
ctaPrimary: '了解我',
|
||||||
|
ctaSecondary: '合作咨询',
|
||||||
|
terminalStatus: '可远程合作,开放全职与项目机会',
|
||||||
|
},
|
||||||
|
trust: {
|
||||||
|
item1: '支持远程协作',
|
||||||
|
item2: '擅长异步协作流程',
|
||||||
|
item3: '产品与工程双视角',
|
||||||
|
item4: '稳定可预期的交付节奏',
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
item1: '重视长期可维护的产品质量',
|
||||||
|
item2: '核心技术栈 TypeScript / React / Node.js',
|
||||||
|
item3: '具备 AI 产品化与工程化经验',
|
||||||
|
item4: '可承接项目合作与全职机会',
|
||||||
|
},
|
||||||
|
services: {
|
||||||
|
eyebrow: '可交付能力',
|
||||||
|
title: '服务方向',
|
||||||
|
description: '从技术方案到落地交付,提供务实可靠的支持。',
|
||||||
|
},
|
||||||
|
career: {
|
||||||
|
eyebrow: '履历速览',
|
||||||
|
title: '关键经历',
|
||||||
|
description: '当前为布局示例数据,后续可替换为你的真实履历。',
|
||||||
|
cta: '查看完整履历',
|
||||||
|
card1: {
|
||||||
|
period: '2024 — 至今',
|
||||||
|
title: 'AI 产品构建者 · 独立开发',
|
||||||
|
outcome: '围绕 AI 场景进行产品探索与快速原型迭代,持续验证方向与可行性。',
|
||||||
|
},
|
||||||
|
card2: {
|
||||||
|
period: '2021 — 2024',
|
||||||
|
title: '高级前端工程师 · 远程团队',
|
||||||
|
outcome: '负责核心前端模块建设,通过可复用架构提升团队交付效率与稳定性。',
|
||||||
|
},
|
||||||
|
card3: {
|
||||||
|
period: '2018 — 2021',
|
||||||
|
title: '全栈工程师 · 成长期团队',
|
||||||
|
outcome: '完成多项面向用户的功能交付,覆盖前后端协作并支撑产品稳定增长。',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
featured: {
|
||||||
|
eyebrow: '代表作品',
|
||||||
|
title: '精选项目',
|
||||||
|
challenge: '挑战',
|
||||||
|
approach: '方案',
|
||||||
|
outcome: '结果',
|
||||||
|
ctaPrimary: '查看项目',
|
||||||
|
ctaSecondary: '了解合作方式',
|
||||||
|
},
|
||||||
|
final: {
|
||||||
|
title: '期待长期且有价值的合作',
|
||||||
|
description: '如果你也在构建高质量产品,并需要稳定执行与协作,我很乐意进一步沟通。',
|
||||||
|
ctaPrimary: '进一步了解我',
|
||||||
|
ctaSecondary: '发起沟通',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,197 +1,101 @@
|
|||||||
---
|
---
|
||||||
import Layout from "@/layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
import GlassHeader from "@/components/GlassHeader";
|
import GlassHeader from "@/components/GlassHeader";
|
||||||
import SkillsMarquee from "@/components/SkillsMarquee";
|
|
||||||
import TypewriterEffect from "@/components/TypewriterEffect";
|
|
||||||
import Footer from "@/components/Footer";
|
import Footer from "@/components/Footer";
|
||||||
import Container from "@/components/ui/Container.astro";
|
import Container from "@/components/ui/Container.astro";
|
||||||
import MotionWrapper from "@/components/MotionWrapper";
|
|
||||||
import { useTranslations } from "@/i18n/utils";
|
import { useTranslations } from "@/i18n/utils";
|
||||||
import type { Lang } from "@/types/i18n";
|
import type { Lang } from "@/types/i18n";
|
||||||
import { defaultLang } from "@/i18n/ui";
|
import { defaultLang } from "@/i18n/ui";
|
||||||
import { personalInfo, services } from "@/lib/data/index";
|
import { personalInfo, services, projects } from "@/lib/data/index";
|
||||||
|
|
||||||
// 使用Astro.currentLocale获取当前语言环境
|
const lang = (Astro.currentLocale as Lang) || defaultLang;
|
||||||
const lang = Astro.currentLocale as Lang || defaultLang;
|
|
||||||
const t = useTranslations(lang);
|
const t = useTranslations(lang);
|
||||||
const pageTitle = t('site.title');
|
const pageTitle = t("site.title");
|
||||||
|
const prefix = lang === "zh" ? "/zh" : "";
|
||||||
|
|
||||||
|
const localizedServices = services[lang];
|
||||||
|
const featuredProject = projects[lang].find((project) => project.featured) ?? projects[lang][0];
|
||||||
|
|
||||||
|
const careerMilestones = [
|
||||||
|
{
|
||||||
|
period: t("home.career.card1.period"),
|
||||||
|
title: t("home.career.card1.title"),
|
||||||
|
outcome: t("home.career.card1.outcome"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: t("home.career.card2.period"),
|
||||||
|
title: t("home.career.card2.title"),
|
||||||
|
outcome: t("home.career.card2.outcome"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: t("home.career.card3.period"),
|
||||||
|
title: t("home.career.card3.title"),
|
||||||
|
outcome: t("home.career.card3.outcome"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const keyFacts = [
|
||||||
|
t("home.trust.item1"),
|
||||||
|
t("home.trust.item3"),
|
||||||
|
t("home.trust.item4"),
|
||||||
|
];
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={pageTitle}>
|
<Layout title={pageTitle}>
|
||||||
<GlassHeader client:only="react" lang={lang} />
|
<GlassHeader client:only="react" lang={lang} />
|
||||||
<main class="min-h-screen">
|
|
||||||
<!-- Hero Section - Inlined Content -->
|
<main class="min-h-screen pb-20">
|
||||||
<section class="py-32 relative overflow-hidden min-h-screen flex flex-col justify-center">
|
<section class="relative flex min-h-[88vh] items-center overflow-hidden py-20 lg:py-24">
|
||||||
<!-- Background gradient -->
|
|
||||||
<div class="page-hero-overlay"></div>
|
<div class="page-hero-overlay"></div>
|
||||||
|
|
||||||
<Container className="relative z-10">
|
<Container className="relative z-10">
|
||||||
<div class="text-center mb-16">
|
<div class="space-y-10">
|
||||||
<!-- Greeting -->
|
<div class="page-content-narrow text-center">
|
||||||
<div class="flex items-center justify-center mb-6">
|
<div class="space-y-5">
|
||||||
<svg class="h-6 w-6 mr-2 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<p class="text-xs font-medium uppercase tracking-[0.22em] text-primary/80">{t("home.hero.eyebrow")}</p>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
<h1 class="text-5xl font-semibold tracking-tight sm:text-6xl lg:text-7xl">{personalInfo.name}</h1>
|
||||||
</svg>
|
<p class="text-xl text-foreground/85 sm:text-2xl">{personalInfo.position[lang]}</p>
|
||||||
<span class="text-primary font-mono text-lg">
|
<p class="mx-auto max-w-3xl text-lg leading-relaxed text-muted-foreground">{t("home.hero.summary")}</p>
|
||||||
{t('hero.greeting')} {personalInfo.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main title -->
|
|
||||||
<h1 class="text-6xl md:text-8xl font-bold mb-6 bg-gradient-to-r from-gray-900 via-blue-600 to-orange-600 dark:from-white dark:via-blue-200 dark:to-orange-300 bg-clip-text text-transparent">
|
|
||||||
{personalInfo.name}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<!-- Subtitle with Typewriter Effect -->
|
|
||||||
<p class="text-2xl md:text-3xl text-muted-foreground mb-8 font-light flex items-center justify-center">
|
|
||||||
<span class="inline-flex items-center">
|
|
||||||
<TypewriterEffect
|
|
||||||
client:load
|
|
||||||
text={[
|
|
||||||
personalInfo.position.en,
|
|
||||||
"Frontend Developer",
|
|
||||||
"TypeScript Enthusiast",
|
|
||||||
"React Specialist",
|
|
||||||
"Full-stack Engineer"
|
|
||||||
]}
|
|
||||||
typingSpeed={100}
|
|
||||||
deletingSpeed={50}
|
|
||||||
delayBeforeDelete={3500}
|
|
||||||
delayBeforeTyping={1800}
|
|
||||||
loop={true}
|
|
||||||
cursorClassName="text-primary dark:text-primary"
|
|
||||||
className="mr-2 font-medium text-muted-foreground"
|
|
||||||
/>
|
|
||||||
<span>👨💻</span>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Description -->
|
|
||||||
<p class="text-lg text-muted-foreground max-w-3xl mx-auto mb-8 leading-relaxed">
|
|
||||||
{personalInfo.description.en}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Job availability notice -->
|
|
||||||
<div class="mb-8">
|
|
||||||
<p class="text-lg font-medium text-primary mb-2">{t('hero.lookingForJob')}</p>
|
|
||||||
<p class="text-md text-muted-foreground">{t('hero.digitalNomad')}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Action buttons -->
|
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center mb-16">
|
|
||||||
<a
|
|
||||||
href={`/${lang === 'zh' ? 'zh/' : ''}hire`}
|
|
||||||
class="bg-primary hover:bg-primary/90 text-white px-8 py-3 rounded-lg font-semibold transition-colors flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
|
||||||
</svg>
|
|
||||||
{t('hero.ctaPrimary')}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href={`/${lang === 'zh' ? 'zh/' : ''}projects`}
|
|
||||||
class="border border-primary text-primary hover:bg-primary hover:text-white px-8 py-3 rounded-lg font-semibold transition-colors flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
|
||||||
</svg>
|
|
||||||
{t('hero.ctaSecondary')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Contact info -->
|
|
||||||
<div class="flex flex-wrap justify-center gap-6 text-sm text-muted-foreground">
|
|
||||||
<div class="flex items-center gap-2 hover:text-foreground transition-colors">
|
|
||||||
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
||||||
</svg>
|
|
||||||
China
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
|
||||||
href={personalInfo.github}
|
<a href={`${prefix}/about`} class="inline-flex h-11 items-center justify-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90">
|
||||||
target="_blank"
|
{t("home.hero.ctaPrimary")}
|
||||||
rel="noopener noreferrer"
|
</a>
|
||||||
class="flex items-center gap-2 hover:text-foreground transition-colors"
|
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center justify-center rounded-lg border border-border bg-background px-6 text-sm font-medium text-foreground hover:bg-muted">
|
||||||
>
|
{t("home.hero.ctaSecondary")}
|
||||||
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
</a>
|
||||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
||||||
</svg>
|
|
||||||
GitHub
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{/* LinkedIn link temporarily hidden
|
|
||||||
<a
|
|
||||||
href={personalInfo.linkedin}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 hover:text-foreground transition-colors"
|
|
||||||
>
|
|
||||||
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
|
||||||
</svg>
|
|
||||||
LinkedIn
|
|
||||||
</a>
|
|
||||||
*/}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Terminal mockup -->
|
|
||||||
<div class="max-w-full mx-auto">
|
|
||||||
<div class="bg-gray-900/90 backdrop-blur-sm rounded-lg border border-gray-700/50 shadow-2xl overflow-hidden">
|
|
||||||
<!-- Terminal header -->
|
|
||||||
<div class="flex items-center justify-between px-4 py-3 bg-gray-800/50 border-b border-gray-700/50">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
|
||||||
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
|
||||||
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-400 text-sm font-mono">
|
|
||||||
{personalInfo.terminal.username}
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Terminal content -->
|
<div class="mt-6 flex flex-wrap items-center justify-center gap-2 text-sm text-muted-foreground">
|
||||||
<div class="p-6 font-mono text-sm">
|
{keyFacts.map((item) => (
|
||||||
<div class="space-y-2">
|
<span class="inline-flex items-center rounded-full border border-border/60 bg-card/60 px-3 py-1">
|
||||||
<div class="flex items-center">
|
{item}
|
||||||
<span class="text-primary mr-2">$</span>
|
</span>
|
||||||
<span class="text-white">whoami</span>
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-primary/80 ml-4">Joy Zhao</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
<div class="page-content-main">
|
||||||
<span class="text-primary mr-2">$</span>
|
<div class="page-surface overflow-hidden rounded-2xl border">
|
||||||
<span class="text-white">cat about.txt</span>
|
<div class="flex items-center justify-between border-b border-border/70 bg-card/70 px-4 py-3">
|
||||||
</div>
|
<div class="flex items-center gap-2">
|
||||||
<div class="text-gray-300 ml-4 leading-relaxed">
|
<span class="h-2.5 w-2.5 rounded-full bg-red-400"></span>
|
||||||
OS: DevOS v4.2.0<br/>
|
<span class="h-2.5 w-2.5 rounded-full bg-yellow-400"></span>
|
||||||
Host: ThinkPad X1 Carbon<br/>
|
<span class="h-2.5 w-2.5 rounded-full bg-green-400"></span>
|
||||||
Kernel: 5.15.0-dev<br/>
|
|
||||||
Uptime: 45 days, 17 hours<br/>
|
|
||||||
Languages: TypeScript, JavaScript, Python<br/>
|
|
||||||
Editor: VSCode / Neovim<br/>
|
|
||||||
Frontend: React, Vue, Next.js, Nuxt.js<br/>
|
|
||||||
Backend: Node.js, Express.js, Nest.js<br/>
|
|
||||||
Database: PostgreSQL, MongoDB<br/>
|
|
||||||
DevOps: Docker, Git, AWS, Cloudflare
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
|
||||||
<span class="text-primary mr-2">$</span>
|
|
||||||
<span class="text-white">ls projects/</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-primary/70 ml-4">
|
|
||||||
taskify-app/ e-commerce-platform/ portfolio-site/
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
|
||||||
<span class="text-primary mr-2">$</span>
|
|
||||||
<span class="text-white animate-pulse">_</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span class="font-mono text-xs text-muted-foreground">{personalInfo.terminal.username}</span>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-2 p-5 font-mono text-xs leading-6 text-foreground/85 sm:text-sm">
|
||||||
|
<p><span class="text-primary">$</span> whoami</p>
|
||||||
|
<p class="pl-4 text-primary/90">{personalInfo.name}</p>
|
||||||
|
<p><span class="text-primary">$</span> role</p>
|
||||||
|
<p class="pl-4">{personalInfo.position[lang]}</p>
|
||||||
|
<p><span class="text-primary">$</span> stack</p>
|
||||||
|
<p class="pl-4">TypeScript, React, Node.js, Astro</p>
|
||||||
|
<p><span class="text-primary">$</span> status</p>
|
||||||
|
<p class="pl-4">{t("home.hero.terminalStatus")}</p>
|
||||||
|
<p><span class="text-primary">$</span> contact</p>
|
||||||
|
<p class="pl-4 text-primary/90">{personalInfo.github}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -199,466 +103,134 @@ const pageTitle = t('site.title');
|
|||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<SkillsMarquee lang={lang} client:only="react" />
|
<section class="py-16">
|
||||||
|
|
||||||
<!-- Featured Project: Elynd -->
|
|
||||||
<section class="py-24 page-section-soft">
|
|
||||||
<Container>
|
<Container>
|
||||||
<div class="text-center mb-12">
|
<div class="mb-10 flex items-end justify-between gap-4">
|
||||||
<span class="inline-block px-4 py-1 bg-primary/20 text-primary dark:text-primary rounded-full text-sm font-medium mb-4">
|
<div class="space-y-2">
|
||||||
{lang === 'zh' ? 'featured 项目' : 'Featured Project'}
|
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.services.eyebrow")}</p>
|
||||||
</span>
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.services.title")}</h2>
|
||||||
<h2 class="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-blue-400 via-primary to-blue-400 bg-clip-text text-transparent">
|
<p class="text-muted-foreground">{t("home.services.description")}</p>
|
||||||
Elynd
|
|
||||||
</h2>
|
|
||||||
<p class="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
||||||
{lang === 'zh'
|
|
||||||
? '一个开放的 AI 工作空间,让构建者能够更智能地工作'
|
|
||||||
: 'An open AI workspace for builders to work smarter'}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto">
|
|
||||||
<div class="page-surface border-primary/20 overflow-hidden">
|
|
||||||
<div class="h-64 md:h-80 bg-gradient-to-br from-primary/20 via-blue-600/20 to-primary/20 flex items-center justify-center relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-grid-primary/10 [mask-image:linear-gradient(0deg,white,rgba(255,255,255,0.3))]"></div>
|
|
||||||
<div class="text-center z-10">
|
|
||||||
<div class="text-6xl md:text-8xl mb-4">⚡</div>
|
|
||||||
<div class="text-2xl md:text-3xl font-bold text-primary">
|
|
||||||
{lang === 'zh' ? '让 AI 成为你的共同构建者' : 'Make AI Your Co-Builder'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-8">
|
|
||||||
<div class="grid md:grid-cols-3 gap-6 mb-8">
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-3xl font-bold text-primary mb-2">AI-First</div>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
{lang === 'zh' ? '从第一天就融入 AI 思维' : 'Built with AI from day one'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-3xl font-bold text-blue-400 mb-2">Open</div>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
{lang === 'zh' ? '完全开放,可自托管' : 'Fully open, self-hostable'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-3xl font-bold text-green-400 mb-2">Builder-First</div>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
{lang === 'zh' ? '为构建者打造的工作空间' : 'Workspace built for builders'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
|
||||||
<a
|
|
||||||
href={`/${lang === 'zh' ? 'zh/' : ''}projects`}
|
|
||||||
class="bg-primary hover:bg-primary/90 text-white px-6 py-3 rounded-lg font-semibold transition-colors inline-flex items-center justify-center gap-2"
|
|
||||||
>
|
|
||||||
<span>🚀</span>
|
|
||||||
{t('hero.ctaSecondary')}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href={`/${lang === 'zh' ? 'zh/' : ''}now`}
|
|
||||||
class="border border-primary text-primary hover:bg-primary hover:text-white px-6 py-3 rounded-lg font-semibold transition-colors inline-flex items-center justify-center gap-2"
|
|
||||||
>
|
|
||||||
<span>📡</span>
|
|
||||||
{lang === 'zh' ? '了解更多' : 'Learn More'}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<a href={`${prefix}/services`} class="hidden text-sm font-medium text-primary hover:text-primary/80 sm:inline-flex">{t("services.viewAll")}</a>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Services Section - Inlined Content -->
|
<div class="grid gap-6 md:grid-cols-2">
|
||||||
<section id="services" class="py-20 bg-gradient-to-br from-slate-50 to-blue-50 dark:from-slate-900 dark:to-slate-800">
|
{localizedServices.map((service) => (
|
||||||
<Container>
|
<article class="page-surface rounded-2xl border p-6 sm:p-8">
|
||||||
<h2 class="text-4xl font-bold text-center mb-16 bg-gradient-to-r from-blue-600 to-primary bg-clip-text text-transparent">
|
<div class="mb-5 flex items-center gap-4">
|
||||||
{t('services.title')}
|
<div class={`flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-br ${service.icon.gradient} text-white`}>
|
||||||
</h2>
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
||||||
<div class="grid md:grid-cols-2 gap-8">
|
|
||||||
{services.en.map((service) => (
|
|
||||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-transform duration-300 hover:scale-105" style="will-change: transform; transform: translateZ(0);">
|
|
||||||
<div class="flex items-center mb-6">
|
|
||||||
<div class={`w-12 h-12 bg-gradient-to-r ${service.icon.gradient} rounded-lg flex items-center justify-center mr-4`}>
|
|
||||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<Fragment set:html={service.icon.svg} />
|
<Fragment set:html={service.icon.svg} />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">{service.title}</h3>
|
<h3 class="text-xl font-semibold tracking-tight">{service.title}</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul class="space-y-3">
|
<ul class="space-y-2 text-sm text-muted-foreground">
|
||||||
{service.items.map((item, index) => (
|
{service.items.slice(0, 3).map((item) => (
|
||||||
<li class="flex items-start">
|
<li class="flex gap-2">
|
||||||
<span class={`text-${service.color}-500 mr-3 mt-1`}>{index + 1}.</span>
|
<span class="mt-1 h-1.5 w-1.5 shrink-0 rounded-full bg-primary/70"></span>
|
||||||
<span class="text-slate-600 dark:text-slate-300">{item}</span>
|
<span>{item}</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-16 page-section-soft">
|
||||||
|
<Container>
|
||||||
|
<div class="mb-10 space-y-2">
|
||||||
|
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.career.eyebrow")}</p>
|
||||||
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.career.title")}</h2>
|
||||||
|
<p class="text-muted-foreground">{t("home.career.description")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page-content-main relative ml-2 border-l border-border/70 pl-6 sm:ml-4 sm:pl-8">
|
||||||
|
{careerMilestones.map((item) => (
|
||||||
|
<div class="relative mb-6 last:mb-0">
|
||||||
|
<span class="absolute -left-[2.1rem] top-2 h-3.5 w-3.5 rounded-full border-2 border-primary/40 bg-background sm:-left-[2.65rem]"></span>
|
||||||
|
<article class="page-surface rounded-xl border p-5">
|
||||||
|
<p class="text-xs font-medium uppercase tracking-[0.14em] text-primary/80">{item.period}</p>
|
||||||
|
<h3 class="mt-3 text-base font-semibold leading-6">{item.title}</h3>
|
||||||
|
<p class="mt-3 text-sm leading-6 text-muted-foreground">{item.outcome}</p>
|
||||||
|
</article>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-12 text-center">
|
<div class="mt-8">
|
||||||
<a href="/services" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-white shadow hover:bg-primary/90 h-10 px-8 py-2">
|
<a href={`${prefix}/about`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
|
||||||
<svg class="h-5 w-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
{t("home.career.cta")}
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
|
|
||||||
</svg>
|
|
||||||
{t('services.viewAll')}
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- About Section - Inlined Content -->
|
<section class="py-16">
|
||||||
<section id="about" class="py-24 relative overflow-hidden">
|
<Container>
|
||||||
<!-- Background gradient -->
|
<div class="mb-8 space-y-2">
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-900/10 via-primary/5 to-indigo-700/10 dark:from-blue-900/20 dark:via-primary/10 dark:to-indigo-700/20"></div>
|
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.featured.eyebrow")}</p>
|
||||||
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.featured.title")}</h2>
|
||||||
<Container className="relative z-10">
|
</div>
|
||||||
<div class="text-center mb-16">
|
|
||||||
<!-- Section Title -->
|
<article class="page-surface rounded-2xl border p-6 sm:p-8">
|
||||||
<div class="flex items-center justify-center mb-6">
|
<div class="flex flex-wrap items-center gap-3">
|
||||||
<h2 class="text-3xl md:text-4xl font-bold bg-gradient-to-r from-blue-600 to-primary bg-clip-text text-transparent">
|
<span class="rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs font-medium text-primary">{t("project.featured")}</span>
|
||||||
{t('about.title')}
|
<h3 class="text-2xl font-semibold">{featuredProject.title}</h3>
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- About Content -->
|
<div class="mt-6 grid gap-6 lg:grid-cols-3">
|
||||||
<div class="grid lg:grid-cols-2 gap-12 items-stretch">
|
<div>
|
||||||
<!-- Left side - Description and Stats -->
|
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.challenge")}</p>
|
||||||
<div class="bg-white/20 dark:bg-gray-800/50 backdrop-blur-sm border border-white/30 dark:border-gray-700/40 rounded-xl p-6 space-y-8">
|
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.impact}</p>
|
||||||
<!-- Description -->
|
|
||||||
<div>
|
|
||||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-6 flex items-center">
|
|
||||||
<span class="mr-2">👋</span>
|
|
||||||
{t('about.sectionTitle')}
|
|
||||||
</h3>
|
|
||||||
<div class="prose prose-lg dark:prose-invert max-w-none">
|
|
||||||
{personalInfo.about[lang].map((paragraph) => (
|
|
||||||
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
|
|
||||||
{paragraph}
|
|
||||||
</p>
|
|
||||||
))} </div>
|
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<a href="/about" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-blue-500 text-white shadow hover:bg-blue-600 h-9 px-4 py-2">
|
|
||||||
<svg class="h-5 w-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
||||||
</svg>
|
|
||||||
{t('about.learnMore')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Stats Grid -->
|
|
||||||
<!-- <div class="grid grid-cols-3 gap-4">
|
|
||||||
<div class="text-center p-4 rounded-xl bg-white/30 dark:bg-gray-700/60 backdrop-blur-sm border border-white/40 dark:border-gray-600/50 hover:bg-white/40 dark:hover:bg-gray-700/80 transition-all duration-300">
|
|
||||||
<svg class="h-8 w-8 mx-auto mb-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
|
||||||
</svg>
|
|
||||||
<div class="text-2xl font-bold text-gray-900 dark:text-white mb-1">
|
|
||||||
{personalInfo.stats.repositories}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
Repositories
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center p-4 rounded-xl bg-white/30 dark:bg-gray-700/60 backdrop-blur-sm border border-white/40 dark:border-gray-600/50 hover:bg-white/40 dark:hover:bg-gray-700/80 transition-all duration-300">
|
|
||||||
<svg class="h-8 w-8 mx-auto mb-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.618 5.984A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016zM12 9v2.25"></path>
|
|
||||||
</svg>
|
|
||||||
<div class="text-2xl font-bold text-gray-900 dark:text-white mb-1">
|
|
||||||
{personalInfo.stats.commits}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
Commits
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center p-4 rounded-xl bg-white/30 dark:bg-gray-700/60 backdrop-blur-sm border border-white/40 dark:border-gray-600/50 hover:bg-white/40 dark:hover:bg-gray-700/80 transition-all duration-300">
|
|
||||||
<svg class="h-8 w-8 mx-auto mb-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
|
|
||||||
</svg>
|
|
||||||
<div class="text-2xl font-bold text-gray-900 dark:text-white mb-1">
|
|
||||||
{personalInfo.stats.contributions}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
PRs Merged
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<!-- Right side - Skills Toolbox -->
|
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.approach")}</p>
|
||||||
<div class="bg-white/20 dark:bg-gray-800/50 backdrop-blur-sm border border-white/30 dark:border-gray-700/40 rounded-xl p-6 flex flex-col">
|
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[0]}</p>
|
||||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-6 flex items-center">
|
|
||||||
<span class="mr-2">💻</span>
|
|
||||||
{t('about.toolbox')}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div class="space-y-6 flex-1">
|
|
||||||
<!-- Skills Progress -->
|
|
||||||
<div class="space-y-4">
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">Frontend</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300 rounded">90%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-blue-500 to-primary h-2 rounded-full" style="width: 90%"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">Backend</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300 rounded">85%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-green-500 to-teal-500 h-2 rounded-full" style="width: 85%"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">DevOps</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-primary/10 dark:bg-primary/10 text-primary/80 dark:text-primary/80 rounded">75%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-primary to-orange-500 h-2 rounded-full" style="width: 75%"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">Mobile</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-orange-100 dark:bg-orange-900/30 text-orange-800 dark:text-orange-300 rounded">65%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-red-500 h-2 rounded-full" style="width: 65%"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tech Stack Tags -->
|
|
||||||
<div>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
{['JavaScript', 'React', 'Node.js', 'TypeScript', 'TailwindCSS', 'Python', 'Docker', 'Git'].map((tech) => (
|
|
||||||
<span
|
|
||||||
class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-full hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
|
|
||||||
>
|
|
||||||
{tech}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.outcome")}</p>
|
||||||
|
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[1]}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 flex flex-wrap gap-2">
|
||||||
|
{featuredProject.tech.slice(0, 4).map((tech) => (
|
||||||
|
<span class="rounded-md border border-border/70 bg-muted/50 px-2.5 py-1 text-xs text-muted-foreground">{tech}</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 flex flex-wrap gap-3">
|
||||||
|
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center rounded-md bg-primary px-5 text-sm font-medium text-primary-foreground hover:bg-primary/90">
|
||||||
|
{t("home.featured.ctaPrimary")}
|
||||||
|
</a>
|
||||||
|
<a href={`${prefix}/hire`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
|
||||||
|
{t("home.featured.ctaSecondary")}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-16">
|
||||||
|
<Container>
|
||||||
|
<div class="page-surface rounded-2xl border px-6 py-10 text-center sm:px-10">
|
||||||
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.final.title")}</h2>
|
||||||
|
<p class="mx-auto mt-4 max-w-2xl text-muted-foreground">{t("home.final.description")}</p>
|
||||||
|
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
|
||||||
|
<a href={`${prefix}/about`} class="inline-flex h-11 items-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground hover:bg-primary/90">
|
||||||
|
{t("home.final.ctaPrimary")}
|
||||||
|
</a>
|
||||||
|
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center rounded-lg border border-border bg-background px-6 text-sm font-medium hover:bg-muted">
|
||||||
|
{t("home.final.ctaSecondary")}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Projects Section - Inlined Content -->
|
|
||||||
<!-- <section id="projects" class="py-20 relative">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-primary/5 to-transparent"></div>
|
|
||||||
|
|
||||||
<Container className="relative z-10">
|
|
||||||
<div class="text-center mb-16">
|
|
||||||
<h2 class="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-blue-400 to-primary bg-clip-text text-transparent">
|
|
||||||
Latest Projects
|
|
||||||
</h2>
|
|
||||||
<p class="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
||||||
A collection of my recent work, showcasing innovative solutions and clean code. Click to explore details.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
|
|
||||||
<div class="page-surface group overflow-hidden border-primary/20 hover:border-primary/40 h-full flex flex-col transition-transform duration-500 hover:scale-105 rounded-xl relative" style="will-change: transform; transform: translateZ(0);">
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
|
||||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="h-48 bg-gradient-to-br from-primary/20 to-primary/20 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-primary/10 to-primary/10 group-hover:from-primary/20 group-hover:to-primary/20 transition-colors duration-500"></div>
|
|
||||||
<div class="absolute bottom-4 left-4 right-4">
|
|
||||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-primary">
|
|
||||||
Taskify App
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pb-4">
|
|
||||||
<h3 class="text-xl group-hover:text-primary transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
|
||||||
<span class="text-primary">📱</span>
|
|
||||||
Taskify App
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 flex-grow">
|
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>A comprehensive task management application with drag-and-drop functionality.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Built with React, TypeScript, and Tailwind CSS for modern development.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Real-time collaboration features with WebSocket integration for instant updates.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Advanced task filtering, sorting, and project management capabilities.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pt-4 border-t border-border/30">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a
|
|
||||||
href="https://github.com/zhaoguiyang/taskify-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 text-sm text-primary hover:text-primary/80 transition-colors group/link"
|
|
||||||
>
|
|
||||||
<span>🔗</span>
|
|
||||||
{t('project.visit')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-surface group overflow-hidden border-primary/20 hover:border-primary/40 h-full flex flex-col transition-transform duration-500 hover:scale-105 rounded-xl relative" style="will-change: transform; transform: translateZ(0);">
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
|
||||||
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.opensource')}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="h-48 bg-gradient-to-br from-primary/20 to-primary/20 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-primary/10 to-primary/10 group-hover:from-primary/20 group-hover:to-primary/20 transition-colors duration-500"></div>
|
|
||||||
<div class="absolute bottom-4 left-4 right-4">
|
|
||||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-primary">
|
|
||||||
E-Shop Platform
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pb-4">
|
|
||||||
<h3 class="text-xl group-hover:text-primary transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
|
||||||
<span class="text-primary">🛒</span>
|
|
||||||
E-Shop Platform
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 flex-grow">
|
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Modern e-commerce solution with comprehensive features for online retail.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Built with Next.js, Prisma, and Stripe for seamless payment processing.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Features shopping cart, payment integration, and admin dashboard.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Responsive design with optimized performance and SEO capabilities.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pt-4 border-t border-border/30">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a
|
|
||||||
href="https://github.com/zhaoguiyang/e-shop-platform"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 text-sm text-green-400 hover:text-green-300 transition-colors group/link"
|
|
||||||
>
|
|
||||||
<span>🔗</span>
|
|
||||||
{t('project.visit')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-surface group overflow-hidden border-primary/20 hover:border-primary/40 h-full flex flex-col transition-transform duration-500 hover:scale-105 rounded-xl relative" style="will-change: transform; transform: translateZ(0);">
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
|
||||||
<span class="px-3 py-1 bg-amber-100 dark:bg-amber-800 text-amber-800 dark:text-amber-200 text-xs rounded-full font-medium border border-amber-200 dark:border-amber-700">{t('project.tag.personal')}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="h-48 bg-gradient-to-br from-primary/20 to-primary/20 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-primary/10 to-primary/10 group-hover:from-primary/20 group-hover:to-primary/20 transition-colors duration-500"></div>
|
|
||||||
<div class="absolute bottom-4 left-4 right-4">
|
|
||||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-primary">
|
|
||||||
Portfolio Site
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pb-4">
|
|
||||||
<h3 class="text-xl group-hover:text-primary transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
|
||||||
<span class="text-primary">🎨</span>
|
|
||||||
Portfolio Site
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 flex-grow">
|
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Responsive personal portfolio website showcasing creative work and projects.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Built with Astro, React, and Tailwind CSS for optimal performance.</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>Features dark mode support and smooth animations for enhanced UX.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Animate</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pt-4 border-t border-border/30">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a
|
|
||||||
href="https://zhaoguiyang.site"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 text-sm text-amber-400 hover:text-amber-300 transition-colors group/link"
|
|
||||||
>
|
|
||||||
<span>🔗</span>
|
|
||||||
{t('project.visit')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</section> -->
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<Footer lang={lang} client:only="react" />
|
<Footer lang={lang} client:only="react" />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@@ -1,197 +1,101 @@
|
|||||||
---
|
---
|
||||||
import Layout from "@/layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
import GlassHeader from "@/components/GlassHeader";
|
import GlassHeader from "@/components/GlassHeader";
|
||||||
import SkillsMarquee from "@/components/SkillsMarquee";
|
|
||||||
import TypewriterEffect from "@/components/TypewriterEffect";
|
|
||||||
import Footer from "@/components/Footer";
|
import Footer from "@/components/Footer";
|
||||||
import Container from "@/components/ui/Container.astro";
|
import Container from "@/components/ui/Container.astro";
|
||||||
import MotionWrapper from "@/components/MotionWrapper";
|
|
||||||
import { useTranslations } from "@/i18n/utils";
|
import { useTranslations } from "@/i18n/utils";
|
||||||
import type { Lang } from "@/types/i18n";
|
import type { Lang } from "@/types/i18n";
|
||||||
import { defaultLang } from "@/i18n/ui";
|
import { defaultLang } from "@/i18n/ui";
|
||||||
import { personalInfo, services } from "@/lib/data/index";
|
import { personalInfo, services, projects } from "@/lib/data/index";
|
||||||
|
|
||||||
// 使用Astro.currentLocale获取当前语言环境
|
const lang = (Astro.currentLocale as Lang) || defaultLang;
|
||||||
const lang = Astro.currentLocale as Lang || defaultLang;
|
|
||||||
const t = useTranslations(lang);
|
const t = useTranslations(lang);
|
||||||
const pageTitle = t('site.title');
|
const pageTitle = t("site.title");
|
||||||
|
const prefix = lang === "zh" ? "/zh" : "";
|
||||||
|
|
||||||
|
const localizedServices = services[lang];
|
||||||
|
const featuredProject = projects[lang].find((project) => project.featured) ?? projects[lang][0];
|
||||||
|
|
||||||
|
const careerMilestones = [
|
||||||
|
{
|
||||||
|
period: t("home.career.card1.period"),
|
||||||
|
title: t("home.career.card1.title"),
|
||||||
|
outcome: t("home.career.card1.outcome"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: t("home.career.card2.period"),
|
||||||
|
title: t("home.career.card2.title"),
|
||||||
|
outcome: t("home.career.card2.outcome"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: t("home.career.card3.period"),
|
||||||
|
title: t("home.career.card3.title"),
|
||||||
|
outcome: t("home.career.card3.outcome"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const keyFacts = [
|
||||||
|
t("home.trust.item1"),
|
||||||
|
t("home.trust.item3"),
|
||||||
|
t("home.trust.item4"),
|
||||||
|
];
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={pageTitle}>
|
<Layout title={pageTitle}>
|
||||||
<GlassHeader client:only="react" lang={lang} />
|
<GlassHeader client:only="react" lang={lang} />
|
||||||
<main class="min-h-screen">
|
|
||||||
<!-- Hero Section - Inlined Content -->
|
<main class="min-h-screen pb-20">
|
||||||
<section class="py-32 relative overflow-hidden min-h-screen flex flex-col justify-center">
|
<section class="relative flex min-h-[88vh] items-center overflow-hidden py-20 lg:py-24">
|
||||||
<!-- Background gradient -->
|
|
||||||
<div class="page-hero-overlay"></div>
|
<div class="page-hero-overlay"></div>
|
||||||
|
|
||||||
<Container className="relative z-10">
|
<Container className="relative z-10">
|
||||||
<div class="text-center mb-16">
|
<div class="space-y-10">
|
||||||
<!-- Greeting -->
|
<div class="page-content-narrow text-center">
|
||||||
<div class="flex items-center justify-center mb-6">
|
<div class="space-y-5">
|
||||||
<svg class="h-6 w-6 mr-2 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<p class="text-xs font-medium uppercase tracking-[0.22em] text-primary/80">{t("home.hero.eyebrow")}</p>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
<h1 class="text-5xl font-semibold tracking-tight sm:text-6xl lg:text-7xl">{personalInfo.name}</h1>
|
||||||
</svg>
|
<p class="text-xl text-foreground/85 sm:text-2xl">{personalInfo.position[lang]}</p>
|
||||||
<span class="text-primary font-mono text-lg">
|
<p class="mx-auto max-w-3xl text-lg leading-relaxed text-muted-foreground">{t("home.hero.summary")}</p>
|
||||||
{t('hero.greeting')} {personalInfo.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main title -->
|
|
||||||
<h1 class="text-6xl md:text-8xl font-bold mb-6 bg-gradient-to-r from-gray-900 via-blue-600 to-orange-600 dark:from-white dark:via-blue-200 dark:to-orange-300 bg-clip-text text-transparent">
|
|
||||||
{personalInfo.name}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<!-- Subtitle with Typewriter Effect -->
|
|
||||||
<p class="text-2xl md:text-3xl text-muted-foreground mb-8 font-light flex items-center justify-center">
|
|
||||||
<span class="inline-flex items-center">
|
|
||||||
<TypewriterEffect
|
|
||||||
client:load
|
|
||||||
text={[
|
|
||||||
personalInfo.position.zh,
|
|
||||||
"前端开发工程师",
|
|
||||||
"TypeScript 爱好者",
|
|
||||||
"React 专家",
|
|
||||||
"全栈工程师"
|
|
||||||
]}
|
|
||||||
typingSpeed={100}
|
|
||||||
deletingSpeed={50}
|
|
||||||
delayBeforeDelete={3500}
|
|
||||||
delayBeforeTyping={1800}
|
|
||||||
loop={true}
|
|
||||||
cursorClassName="text-primary dark:text-primary"
|
|
||||||
className="mr-2 font-medium text-muted-foreground"
|
|
||||||
/>
|
|
||||||
<span>👨💻</span>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Description -->
|
|
||||||
<p class="text-lg text-muted-foreground max-w-3xl mx-auto mb-8 leading-relaxed">
|
|
||||||
{personalInfo.description.zh}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Job availability notice -->
|
|
||||||
<div class="mb-8">
|
|
||||||
<p class="text-lg font-medium text-primary mb-2">{t('hero.lookingForJob')}</p>
|
|
||||||
<p class="text-md text-muted-foreground">{t('hero.digitalNomad')}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Action buttons -->
|
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center mb-16">
|
|
||||||
<a
|
|
||||||
href="/zh/hire"
|
|
||||||
class="bg-primary hover:bg-primary/90 text-white px-8 py-3 rounded-lg font-semibold transition-colors flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
|
||||||
</svg>
|
|
||||||
{t('hero.ctaPrimary')}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="/zh/projects"
|
|
||||||
class="border border-primary text-primary hover:bg-primary hover:text-white px-8 py-3 rounded-lg font-semibold transition-colors flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
|
||||||
</svg>
|
|
||||||
{t('hero.ctaSecondary')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Contact info -->
|
|
||||||
<div class="flex flex-wrap justify-center gap-6 text-sm text-muted-foreground">
|
|
||||||
<div class="flex items-center gap-2 hover:text-foreground transition-colors">
|
|
||||||
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
||||||
</svg>
|
|
||||||
中国
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
|
||||||
href={personalInfo.github}
|
<a href={`${prefix}/about`} class="inline-flex h-11 items-center justify-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90">
|
||||||
target="_blank"
|
{t("home.hero.ctaPrimary")}
|
||||||
rel="noopener noreferrer"
|
</a>
|
||||||
class="flex items-center gap-2 hover:text-foreground transition-colors"
|
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center justify-center rounded-lg border border-border bg-background px-6 text-sm font-medium text-foreground hover:bg-muted">
|
||||||
>
|
{t("home.hero.ctaSecondary")}
|
||||||
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
</a>
|
||||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.30.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
||||||
</svg>
|
|
||||||
GitHub
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{/* LinkedIn link temporarily hidden
|
|
||||||
<a
|
|
||||||
href={personalInfo.linkedin}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 hover:text-foreground transition-colors"
|
|
||||||
>
|
|
||||||
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
|
||||||
</svg>
|
|
||||||
领英
|
|
||||||
</a>
|
|
||||||
*/}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Terminal mockup -->
|
|
||||||
<div class="max-w-full mx-auto">
|
|
||||||
<div class="bg-gray-900/90 backdrop-blur-sm rounded-lg border border-gray-700/50 shadow-2xl overflow-hidden">
|
|
||||||
<!-- Terminal header -->
|
|
||||||
<div class="flex items-center justify-between px-4 py-3 bg-gray-800/50 border-b border-gray-700/50">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
|
||||||
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
|
||||||
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
|
||||||
</div>
|
|
||||||
<div class="text-gray-400 text-sm font-mono">
|
|
||||||
{personalInfo.terminal.username}
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Terminal content -->
|
<div class="mt-6 flex flex-wrap items-center justify-center gap-2 text-sm text-muted-foreground">
|
||||||
<div class="p-6 font-mono text-sm">
|
{keyFacts.map((item) => (
|
||||||
<div class="space-y-2">
|
<span class="inline-flex items-center rounded-full border border-border/60 bg-card/60 px-3 py-1">
|
||||||
<div class="flex items-center">
|
{item}
|
||||||
<span class="text-primary mr-2">$</span>
|
</span>
|
||||||
<span class="text-white">whoami</span>
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-primary/80 ml-4">Joy Zhao</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
<div class="page-content-main">
|
||||||
<span class="text-primary mr-2">$</span>
|
<div class="page-surface overflow-hidden rounded-2xl border">
|
||||||
<span class="text-white">cat about.txt</span>
|
<div class="flex items-center justify-between border-b border-border/70 bg-card/70 px-4 py-3">
|
||||||
</div>
|
<div class="flex items-center gap-2">
|
||||||
<div class="text-gray-300 ml-4 leading-relaxed">
|
<span class="h-2.5 w-2.5 rounded-full bg-red-400"></span>
|
||||||
操作系统: DevOS v4.2.0<br/>
|
<span class="h-2.5 w-2.5 rounded-full bg-yellow-400"></span>
|
||||||
主机: ThinkPad X1 Carbon<br/>
|
<span class="h-2.5 w-2.5 rounded-full bg-green-400"></span>
|
||||||
内核: 5.15.0-dev<br/>
|
|
||||||
运行时间: 45 天, 17 小时<br/>
|
|
||||||
编程语言: TypeScript, JavaScript, Python<br/>
|
|
||||||
编辑器: VSCode / Neovim<br/>
|
|
||||||
前端技术: React, Vue, Next.js, Nuxt.js<br/>
|
|
||||||
后端技术: Node.js, Express.js, Nest.js<br/>
|
|
||||||
数据库: PostgreSQL, MongoDB<br/>
|
|
||||||
DevOps: Docker, Git, AWS, Cloudflare
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
|
||||||
<span class="text-primary mr-2">$</span>
|
|
||||||
<span class="text-white">ls projects/</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-primary/70 ml-4">
|
|
||||||
taskify-app/ e-commerce-platform/ portfolio-site/
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
|
||||||
<span class="text-primary mr-2">$</span>
|
|
||||||
<span class="text-white animate-pulse">_</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span class="font-mono text-xs text-muted-foreground">{personalInfo.terminal.username}</span>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-2 p-5 font-mono text-xs leading-6 text-foreground/85 sm:text-sm">
|
||||||
|
<p><span class="text-primary">$</span> whoami</p>
|
||||||
|
<p class="pl-4 text-primary/90">{personalInfo.name}</p>
|
||||||
|
<p><span class="text-primary">$</span> role</p>
|
||||||
|
<p class="pl-4">{personalInfo.position[lang]}</p>
|
||||||
|
<p><span class="text-primary">$</span> stack</p>
|
||||||
|
<p class="pl-4">TypeScript, React, Node.js, Astro</p>
|
||||||
|
<p><span class="text-primary">$</span> status</p>
|
||||||
|
<p class="pl-4">{t("home.hero.terminalStatus")}</p>
|
||||||
|
<p><span class="text-primary">$</span> contact</p>
|
||||||
|
<p class="pl-4 text-primary/90">{personalInfo.github}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -199,457 +103,134 @@ const pageTitle = t('site.title');
|
|||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<SkillsMarquee lang={lang} client:only="react" />
|
<section class="py-16">
|
||||||
|
|
||||||
<!-- Featured Project: Elynd -->
|
|
||||||
<section class="py-24 page-section-soft">
|
|
||||||
<Container>
|
<Container>
|
||||||
<div class="text-center mb-12">
|
<div class="mb-10 flex items-end justify-between gap-4">
|
||||||
<span class="inline-block px-4 py-1 bg-primary/20 text-primary dark:text-primary rounded-full text-sm font-medium mb-4">
|
<div class="space-y-2">
|
||||||
Featured 项目
|
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.services.eyebrow")}</p>
|
||||||
</span>
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.services.title")}</h2>
|
||||||
<h2 class="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-blue-400 via-blue-400 to-blue-400 bg-clip-text text-transparent">
|
<p class="text-muted-foreground">{t("home.services.description")}</p>
|
||||||
Elynd
|
|
||||||
</h2>
|
|
||||||
<p class="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
||||||
一个开放的 AI 工作空间,让构建者能够更智能地工作
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto">
|
|
||||||
<div class="page-surface border-primary/20 overflow-hidden">
|
|
||||||
<div class="h-64 md:h-80 bg-gradient-to-br from-primary/20 via-blue-600/20 to-primary/20 flex items-center justify-center relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-grid-primary/10 [mask-image:linear-gradient(0deg,white,rgba(255,255,255,0.3))]"></div>
|
|
||||||
<div class="text-center z-10">
|
|
||||||
<div class="text-6xl md:text-8xl mb-4">⚡</div>
|
|
||||||
<div class="text-2xl md:text-3xl font-bold text-primary">
|
|
||||||
让 AI 成为你的共同构建者
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-8">
|
|
||||||
<div class="grid md:grid-cols-3 gap-6 mb-8">
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-3xl font-bold text-primary mb-2">AI-First</div>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
从第一天就融入 AI 思维
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-3xl font-bold text-blue-400 mb-2">Open</div>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
完全开放,可自托管
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-3xl font-bold text-green-400 mb-2">Builder-First</div>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
为构建者打造的工作空间
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
|
||||||
<a
|
|
||||||
href="/zh/projects"
|
|
||||||
class="bg-primary hover:bg-primary/90 text-white px-6 py-3 rounded-lg font-semibold transition-colors inline-flex items-center justify-center gap-2"
|
|
||||||
>
|
|
||||||
<span>🚀</span>
|
|
||||||
{t('hero.ctaSecondary')}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="/zh/now"
|
|
||||||
class="border border-primary text-primary hover:bg-primary hover:text-white px-6 py-3 rounded-lg font-semibold transition-colors inline-flex items-center justify-center gap-2"
|
|
||||||
>
|
|
||||||
<span>📡</span>
|
|
||||||
了解更多
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<a href={`${prefix}/services`} class="hidden text-sm font-medium text-primary hover:text-primary/80 sm:inline-flex">{t("services.viewAll")}</a>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Services Section - Inlined Content -->
|
<div class="grid gap-6 md:grid-cols-2">
|
||||||
<section id="services" class="py-20 px-4 bg-gradient-to-br from-slate-50 to-blue-50 dark:from-slate-900 dark:to-slate-800">
|
{localizedServices.map((service) => (
|
||||||
<Container>
|
<article class="page-surface rounded-2xl border p-6 sm:p-8">
|
||||||
<h2 class="text-4xl font-bold text-center mb-16 bg-gradient-to-r from-blue-600 to-primary bg-clip-text text-transparent">
|
<div class="mb-5 flex items-center gap-4">
|
||||||
{t('services.title')}
|
<div class={`flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-br ${service.icon.gradient} text-white`}>
|
||||||
</h2>
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
||||||
<div class="grid md:grid-cols-2 gap-8">
|
|
||||||
{services.zh.map((service) => (
|
|
||||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-transform duration-300 hover:scale-105" style="will-change: transform; transform: translateZ(0);">
|
|
||||||
<div class="flex items-center mb-6">
|
|
||||||
<div class={`w-12 h-12 bg-gradient-to-r ${service.icon.gradient} rounded-lg flex items-center justify-center mr-4`}>
|
|
||||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<Fragment set:html={service.icon.svg} />
|
<Fragment set:html={service.icon.svg} />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">{service.title}</h3>
|
<h3 class="text-xl font-semibold tracking-tight">{service.title}</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul class="space-y-3">
|
<ul class="space-y-2 text-sm text-muted-foreground">
|
||||||
{service.items.map((item, index) => (
|
{service.items.slice(0, 3).map((item) => (
|
||||||
<li class="flex items-start">
|
<li class="flex gap-2">
|
||||||
<span class={`text-${service.color}-500 mr-3 mt-1`}>{index + 1}.</span>
|
<span class="mt-1 h-1.5 w-1.5 shrink-0 rounded-full bg-primary/70"></span>
|
||||||
<span class="text-slate-600 dark:text-slate-300">{item}</span>
|
<span>{item}</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-16 page-section-soft">
|
||||||
|
<Container>
|
||||||
|
<div class="mb-10 space-y-2">
|
||||||
|
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.career.eyebrow")}</p>
|
||||||
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.career.title")}</h2>
|
||||||
|
<p class="text-muted-foreground">{t("home.career.description")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page-content-main relative ml-2 border-l border-border/70 pl-6 sm:ml-4 sm:pl-8">
|
||||||
|
{careerMilestones.map((item) => (
|
||||||
|
<div class="relative mb-6 last:mb-0">
|
||||||
|
<span class="absolute -left-[2.1rem] top-2 h-3.5 w-3.5 rounded-full border-2 border-primary/40 bg-background sm:-left-[2.65rem]"></span>
|
||||||
|
<article class="page-surface rounded-xl border p-5">
|
||||||
|
<p class="text-xs font-medium uppercase tracking-[0.14em] text-primary/80">{item.period}</p>
|
||||||
|
<h3 class="mt-3 text-base font-semibold leading-6">{item.title}</h3>
|
||||||
|
<p class="mt-3 text-sm leading-6 text-muted-foreground">{item.outcome}</p>
|
||||||
|
</article>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-12 text-center">
|
<div class="mt-8">
|
||||||
<a href="/zh/services" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-white shadow hover:bg-primary/90 h-10 px-8 py-2">
|
<a href={`${prefix}/about`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
|
||||||
<svg class="h-5 w-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
{t("home.career.cta")}
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
|
|
||||||
</svg>
|
|
||||||
{t('services.viewAll')}
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- About Section - Inlined Content -->
|
<section class="py-16">
|
||||||
<section id="about" class="py-24 relative overflow-hidden">
|
<Container>
|
||||||
<!-- Background gradient -->
|
<div class="mb-8 space-y-2">
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-900/10 via-primary/5 to-indigo-700/10 dark:from-blue-900/20 dark:via-primary/10 dark:to-indigo-700/20"></div>
|
<p class="text-sm font-medium uppercase tracking-[0.2em] text-primary/80">{t("home.featured.eyebrow")}</p>
|
||||||
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.featured.title")}</h2>
|
||||||
<Container className="relative z-10">
|
</div>
|
||||||
<div class="text-center mb-16">
|
|
||||||
<!-- Section Title -->
|
<article class="page-surface rounded-2xl border p-6 sm:p-8">
|
||||||
<div class="flex items-center justify-center mb-6">
|
<div class="flex flex-wrap items-center gap-3">
|
||||||
<h2 class="text-3xl md:text-4xl font-bold bg-gradient-to-r from-blue-600 to-primary bg-clip-text text-transparent">
|
<span class="rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs font-medium text-primary">{t("project.featured")}</span>
|
||||||
{t('about.title')}
|
<h3 class="text-2xl font-semibold">{featuredProject.title}</h3>
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- About Content -->
|
<div class="mt-6 grid gap-6 lg:grid-cols-3">
|
||||||
<div class="grid lg:grid-cols-2 gap-12 items-stretch">
|
<div>
|
||||||
<!-- Left side - Description and Stats -->
|
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.challenge")}</p>
|
||||||
<div class="bg-white/20 dark:bg-gray-800/50 backdrop-blur-sm border border-white/30 dark:border-gray-700/40 rounded-xl p-6 space-y-8">
|
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.impact}</p>
|
||||||
<!-- Description -->
|
|
||||||
<div>
|
|
||||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-6 flex items-center">
|
|
||||||
<span class="mr-2">👋</span>
|
|
||||||
{t('about.sectionTitle')}
|
|
||||||
</h3>
|
|
||||||
<div class="prose prose-lg dark:prose-invert max-w-none">
|
|
||||||
{personalInfo.about[lang].map((paragraph) => (
|
|
||||||
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
|
|
||||||
{paragraph}
|
|
||||||
</p>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<a href="/zh/about" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-blue-500 text-white shadow hover:bg-blue-600 h-9 px-4 py-2">
|
|
||||||
<svg class="h-5 w-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
||||||
</svg>
|
|
||||||
{t('about.learnMore')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Stats Grid -->
|
|
||||||
<!-- <div class="grid grid-cols-3 gap-4">
|
|
||||||
<div class="text-center p-4 rounded-xl bg-white/30 dark:bg-gray-700/60 backdrop-blur-sm border border-white/40 dark:border-gray-600/50 hover:bg-white/40 dark:hover:bg-gray-700/80 transition-all duration-300">
|
|
||||||
<svg class="h-8 w-8 mx-auto mb-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
|
||||||
</svg>
|
|
||||||
<div class="text-2xl font-bold text-gray-900 dark:text-white mb-1">
|
|
||||||
{personalInfo.stats.repositories}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
仓库数量
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center p-4 rounded-xl bg-white/30 dark:bg-gray-700/60 backdrop-blur-sm border border-white/40 dark:border-gray-600/50 hover:bg-white/40 dark:hover:bg-gray-700/80 transition-all duration-300">
|
|
||||||
<svg class="h-8 w-8 mx-auto mb-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.618 5.984A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016zM12 9v2.25"></path>
|
|
||||||
</svg>
|
|
||||||
<div class="text-2xl font-bold text-gray-900 dark:text-white mb-1">
|
|
||||||
{personalInfo.stats.commits}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
提交次数
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center p-4 rounded-xl bg-white/30 dark:bg-gray-700/60 backdrop-blur-sm border border-white/40 dark:border-gray-600/50 hover:bg-white/40 dark:hover:bg-gray-700/80 transition-all duration-300">
|
|
||||||
<svg class="h-8 w-8 mx-auto mb-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
|
|
||||||
</svg>
|
|
||||||
<div class="text-2xl font-bold text-gray-900 dark:text-white mb-1">
|
|
||||||
{personalInfo.stats.contributions}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
PR合并数
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<!-- Right side - Skills Toolbox -->
|
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.approach")}</p>
|
||||||
<div class="bg-white/20 dark:bg-gray-800/50 backdrop-blur-sm border border-white/30 dark:border-gray-700/40 rounded-xl p-6 flex flex-col">
|
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[0]}</p>
|
||||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-6 flex items-center">
|
|
||||||
<span class="mr-2">💻</span>
|
|
||||||
{t('about.toolbox')}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div class="space-y-6 flex-1">
|
|
||||||
<!-- Skills Progress -->
|
|
||||||
<div class="space-y-4">
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">前端开发</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300 rounded">90%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-blue-500 to-primary h-2 rounded-full" style="width: 90%"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">后端开发</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300 rounded">85%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-green-500 to-teal-500 h-2 rounded-full" style="width: 85%"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">DevOps</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-primary/10 dark:bg-primary/10 text-primary/80 dark:text-primary/80 rounded">75%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-primary to-orange-500 h-2 rounded-full" style="width: 75%"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-sm text-gray-700 dark:text-gray-300">移动开发</span>
|
|
||||||
<span class="px-2 py-1 text-xs bg-orange-100 dark:bg-orange-900/30 text-orange-800 dark:text-orange-300 rounded">65%</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-red-500 h-2 rounded-full" style="width: 65%"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tech Stack Tags -->
|
|
||||||
<div>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
{['JavaScript', 'React', 'Node.js', 'TypeScript', 'TailwindCSS', 'Python', 'Docker', 'Git'].map((tech) => (
|
|
||||||
<span
|
|
||||||
class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-full hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
|
|
||||||
>
|
|
||||||
{tech}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-xs uppercase tracking-[0.14em] text-muted-foreground">{t("home.featured.outcome")}</p>
|
||||||
|
<p class="mt-2 text-sm leading-6 text-foreground/85">{featuredProject.description[1]}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 flex flex-wrap gap-2">
|
||||||
|
{featuredProject.tech.slice(0, 4).map((tech) => (
|
||||||
|
<span class="rounded-md border border-border/70 bg-muted/50 px-2.5 py-1 text-xs text-muted-foreground">{tech}</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 flex flex-wrap gap-3">
|
||||||
|
<a href={`${prefix}/projects`} class="inline-flex h-10 items-center rounded-md bg-primary px-5 text-sm font-medium text-primary-foreground hover:bg-primary/90">
|
||||||
|
{t("home.featured.ctaPrimary")}
|
||||||
|
</a>
|
||||||
|
<a href={`${prefix}/hire`} class="inline-flex h-10 items-center rounded-md border border-border bg-background px-5 text-sm font-medium hover:bg-muted">
|
||||||
|
{t("home.featured.ctaSecondary")}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-16">
|
||||||
|
<Container>
|
||||||
|
<div class="page-surface rounded-2xl border px-6 py-10 text-center sm:px-10">
|
||||||
|
<h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">{t("home.final.title")}</h2>
|
||||||
|
<p class="mx-auto mt-4 max-w-2xl text-muted-foreground">{t("home.final.description")}</p>
|
||||||
|
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
|
||||||
|
<a href={`${prefix}/about`} class="inline-flex h-11 items-center rounded-lg bg-primary px-6 text-sm font-medium text-primary-foreground hover:bg-primary/90">
|
||||||
|
{t("home.final.ctaPrimary")}
|
||||||
|
</a>
|
||||||
|
<a href={`${prefix}/hire`} class="inline-flex h-11 items-center rounded-lg border border-border bg-background px-6 text-sm font-medium hover:bg-muted">
|
||||||
|
{t("home.final.ctaSecondary")}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Projects Section - Inlined Content -->
|
|
||||||
<!-- <section id="projects" class="py-20 relative">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-primary/5 to-transparent"></div>
|
|
||||||
|
|
||||||
<Container className="relative z-10">
|
|
||||||
<div class="text-center mb-16">
|
|
||||||
<h2 class="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-blue-400 to-primary bg-clip-text text-transparent">
|
|
||||||
我的项目
|
|
||||||
</h2>
|
|
||||||
<p class="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
||||||
我最近工作的精选集合,展示创新解决方案和简洁代码。点击探索详情。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
|
|
||||||
<div class="page-surface group overflow-hidden border-primary/20 hover:border-primary/40 h-full flex flex-col transition-all duration-500 hover:scale-105 rounded-xl relative">
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
|
||||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="h-48 bg-gradient-to-br from-primary/20 to-primary/20 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-primary/10 to-primary/10 group-hover:from-primary/20 group-hover:to-primary/20 transition-all duration-500"></div>
|
|
||||||
<div class="absolute bottom-4 left-4 right-4">
|
|
||||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-primary">
|
|
||||||
Taskify App
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pb-4">
|
|
||||||
<h3 class="text-xl group-hover:text-primary transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
|
||||||
<span class="text-primary">📱</span>
|
|
||||||
Taskify 应用
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 flex-grow">
|
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>一个功能完整的任务管理应用程序</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>使用 React、TypeScript 和 Tailwind CSS 构建</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>具有拖放功能和实时更新</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pt-4 border-t border-border/30">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a
|
|
||||||
href="https://github.com/zhaoguiyang/taskify-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 text-sm text-primary hover:text-primary/80 transition-colors group/link"
|
|
||||||
>
|
|
||||||
<span>🔗</span>
|
|
||||||
{t('project.visit')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-surface group overflow-hidden border-primary/20 hover:border-primary/40 h-full flex flex-col transition-all duration-500 hover:scale-105 rounded-xl relative">
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
|
||||||
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.opensource')}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="h-48 bg-gradient-to-br from-primary/20 to-primary/20 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-primary/10 to-primary/10 group-hover:from-primary/20 group-hover:to-primary/20 transition-all duration-500"></div>
|
|
||||||
<div class="absolute bottom-4 left-4 right-4">
|
|
||||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-primary">
|
|
||||||
E-Shop Platform
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pb-4">
|
|
||||||
<h3 class="text-xl group-hover:text-primary transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
|
||||||
<span class="text-primary">📱</span>
|
|
||||||
电商平台
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 flex-grow">
|
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>现代化的电子商务解决方案</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>使用 Next.js、Prisma 和 Stripe 构建</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>具有购物车、支付和管理面板功能</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pt-4 border-t border-border/30">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a
|
|
||||||
href="https://github.com/zhaoguiyang/e-shop-platform"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 text-sm text-green-400 hover:text-green-300 transition-colors group/link"
|
|
||||||
>
|
|
||||||
<span>🔗</span>
|
|
||||||
{t('project.visit')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-surface group overflow-hidden border-primary/20 hover:border-primary/40 h-full flex flex-col transition-all duration-500 hover:scale-105 rounded-xl relative">
|
|
||||||
<div class="absolute top-4 right-4 z-10">
|
|
||||||
<span class="px-3 py-1 bg-amber-100 dark:bg-amber-800 text-amber-800 dark:text-amber-200 text-xs rounded-full font-medium border border-amber-200 dark:border-amber-700">{t('project.tag.personal')}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="h-48 bg-gradient-to-br from-primary/20 to-primary/20 relative overflow-hidden">
|
|
||||||
<div class="absolute inset-0 bg-gradient-to-br from-primary/10 to-primary/10 group-hover:from-primary/20 group-hover:to-primary/20 transition-all duration-500"></div>
|
|
||||||
<div class="absolute bottom-4 left-4 right-4">
|
|
||||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-primary">
|
|
||||||
Portfolio Site
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pb-4">
|
|
||||||
<h3 class="text-xl group-hover:text-primary transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
|
||||||
<span class="text-primary">📱</span>
|
|
||||||
个人作品集
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 flex-grow">
|
|
||||||
<div class="space-y-3">
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>响应式个人作品集网站</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>使用 Astro、React 和 Tailwind CSS 构建</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
|
||||||
<span class="text-primary mt-1">•</span>
|
|
||||||
<span>具有深色模式和平滑动画效果</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
|
||||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Animate</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-6 pt-4 border-t border-border/30">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<a
|
|
||||||
href="https://zhaoguiyang.site"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-2 text-sm text-amber-400 hover:text-amber-300 transition-colors group/link"
|
|
||||||
>
|
|
||||||
<span>🔗</span>
|
|
||||||
{t('project.visit')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</section> -->
|
|
||||||
</main>
|
</main>
|
||||||
<Footer lang={lang} client:load />
|
|
||||||
|
<Footer lang={lang} client:only="react" />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
Reference in New Issue
Block a user