diff --git a/public/fly-signal.png b/public/fly-signal.png new file mode 100644 index 0000000..6ed2363 Binary files /dev/null and b/public/fly-signal.png differ diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..72df76b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,62 @@ @import "tailwindcss"; :root { - --background: #ffffff; - --foreground: #171717; + --background: #101411; + --foreground: #f4efe4; } @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); + --font-sans: var(--font-body); + --font-mono: var(--font-code); + --font-display: var(--font-heading); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; } body { + margin: 0; background: var(--background); color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + font-family: var(--font-body), sans-serif; +} + +::selection { + background: #d3ff30; + color: #101411; +} + +a { + text-decoration: none; +} + +.noise-layer { + position: absolute; + inset: 0; + z-index: -1; + pointer-events: none; + opacity: 0.2; + background-image: + radial-gradient(circle at 18% 30%, rgba(244, 239, 228, 0.18) 0 1px, transparent 1px), + radial-gradient(circle at 72% 64%, rgba(211, 255, 48, 0.14) 0 1px, transparent 1px); + background-size: 34px 34px, 46px 46px; + mix-blend-mode: screen; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 976eb90..516ec3d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,20 +1,28 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { JetBrains_Mono, Newsreader, Noto_Sans_SC } from "next/font/google"; import "./globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", +const display = Newsreader({ + variable: "--font-heading", subsets: ["latin"], + display: "swap", }); -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", +const sans = Noto_Sans_SC({ + variable: "--font-body", subsets: ["latin"], + display: "swap", +}); + +const mono = JetBrains_Mono({ + variable: "--font-code", + subsets: ["latin"], + display: "swap", }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "fly | Personal Website", + description: "fly 的个人网站,记录前端开发、技术笔记和页面实验。", }; export default function RootLayout({ @@ -24,8 +32,8 @@ export default function RootLayout({ }>) { return ( {children} diff --git a/src/app/page.tsx b/src/app/page.tsx index 3f36f7c..a83dc91 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,65 +1,5 @@ -import Image from "next/image"; +import { HomePage } from "@/components/home-page"; export default function Home() { - return ( -
-
- Next.js logo -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
-
- - Vercel logomark - Deploy Now - - - Documentation - -
-
-
- ); + return ; } diff --git a/src/components/home-page.tsx b/src/components/home-page.tsx new file mode 100644 index 0000000..3a6cd2f --- /dev/null +++ b/src/components/home-page.tsx @@ -0,0 +1,217 @@ +"use client"; + +import Image from "next/image"; +import { motion, useReducedMotion } from "motion/react"; + +const highlights = [ + { label: "Frontend", value: "React / Vue / Next.js" }, + { label: "Notes", value: "HTML, CSS, JS, Git" }, + { label: "Current", value: "Rebuilding a personal web identity" }, +]; + +const chapters = [ + { + title: "Engineering Notes", + eyebrow: "01", + body: "把前端知识拆成可复用的笔记,不追求堆砌,追求每次回看都能拿来解决问题。", + href: "http://124.221.147.173:3000/fly/flys_blog", + }, + { + title: "Personal Experiments", + eyebrow: "02", + body: "记录一些页面、工具、交互和生活灵感,把学习过程变成能被看见的作品。", + href: "http://124.221.147.173:3000/fly/fly-personal-site", + }, + { + title: "Quiet Systems", + eyebrow: "03", + body: "偏爱清晰、克制、有质感的界面。让复杂内容保持秩序,让细节自己发光。", + href: "#signal", + }, +]; + +const stack = [ + "Next.js", + "Tailwind CSS", + "Motion", + "TypeScript", + "Vue", + "React", + "Git", + "VitePress", +]; + +export function HomePage() { + const reduceMotion = useReducedMotion(); + + const reveal = { + hidden: { opacity: 0, y: reduceMotion ? 0 : 24 }, + show: { opacity: 1, y: 0 }, + }; + + return ( +
+
+
+
+
+ +
+ + + + + fly + + + + +
+ + Personal website / frontend notes / visual experiments + + + fly + + + 前端开发者,正在把技术笔记、页面实验和个人审美重新整理成一个更自由、更有质感的个人网站。 + + + + 查看主页结构 + + + 打开旧博客仓库 + + +
+ + + {highlights.map((item) => ( +
+

{item.label}

+

{item.value}

+
+ ))} +
+
+ + +
+
+ Abstract fly personal field notes artwork +
+
+

signal

+

+ A new home for notes, projects, experiments, and the quiet parts of making things. +

+
+ +
+
+ +
+
+
+
+

What this site becomes

+

+ 一个更像 fly 的个人主页。 +

+
+ +
+
+
+ +
+
+
+

Stack and rhythm

+

+ 写代码,也整理判断。 +

+

+ 首页先完成品牌感和结构感。后续可以接入 MDX 博客、项目详情页、关于页和部署流程,把旧 VitePress 的内容慢慢迁过来。 +

+
+
+ {stack.map((item) => ( + + {item} + + ))} +
+
+
+
+ ); +}