From 1b495d2d2d03e8adf91c2a0fc2b97a7e21f2c5b8 Mon Sep 17 00:00:00 2001 From: gbanyan Date: Sat, 14 Mar 2026 23:00:21 +0800 Subject: [PATCH] Remove next-view-transitions and use native View Transition API - Remove external next-view-transitions dependency - Use Next.js 16 native navigation and Safari 18+ native View Transition API - Add ViewTransitionProvider for minimal wrapping with Safari 18+ detection - Updated all Link imports from external package to next/link - Removed link-wrapper.tsx and view-transitions-wrapper.tsx This resolves Safari compatibility issues while maintaining transitions on modern browsers. --- CLAUDE.md | 50 + app/blog/[slug]/page.tsx | 4 +- app/blog/page.tsx | 2 +- app/layout.tsx | 62 +- app/page.tsx | 4 +- app/pages/[slug]/page.tsx | 2 +- app/tags/page.tsx | 4 +- app/template.tsx | 27 +- components/app-wrapper.tsx | 14 + components/back-to-top.tsx | 2 +- components/matrix-rain.tsx | 31 +- components/meta-item.tsx | 10 +- components/native-link.tsx | 20 + components/nav-menu.tsx | 28 +- components/post-card.tsx | 16 +- components/post-layout.tsx | 12 +- components/post-list-item.tsx | 8 +- components/post-storyline-nav.tsx | 2 +- components/reading-progress.tsx | 35 +- components/repo-card.tsx | 10 +- components/right-sidebar.tsx | 53 +- components/scroll-reveal.tsx | 43 +- components/search-modal.tsx | 22 +- components/sidebar-layout.tsx | 8 +- components/site-footer.tsx | 2 +- components/site-header.tsx | 4 +- components/theme-toggle.tsx | 6 +- components/timeline-wrapper.tsx | 20 +- components/view-transition-provider.tsx | 19 + lib/config.ts | 8 +- package-lock.json | 1377 +++++++++++++---------- package.json | 1 - styles/globals.css | 48 +- 33 files changed, 1124 insertions(+), 830 deletions(-) create mode 100644 components/app-wrapper.tsx create mode 100644 components/native-link.tsx create mode 100644 components/view-transition-provider.tsx diff --git a/CLAUDE.md b/CLAUDE.md index 8df3e70..22d3801 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -70,3 +70,53 @@ Pushing only to `content/` (personal-blog) does NOT trigger deployment. The main ## Language The site's default locale is `zh-TW`. UI text, labels, and timestamps are in Traditional Chinese. + +## Design Context + +### Users + +- **Medical professionals & students**: Seek clinical insights, case studies, and medical education content +- **General public**: Interested inpersonal reflections, medicine explainedaccessibly, and lifestyle content +- **Tech enthusiasts & developers**: Drawn to HomeLab, technical tutorials, and developer environment content +- **Patients & advocates**: Those with similar conditions (Usher syndrome, hearing/vision impairments) seeking understanding and community + +**Context**: Readers visit for deep, reflective content—often in quiet environments, seeking to learn, reflect, or connect with personal experiences. They value clarity, authenticity, and quality over speed. + +**Job to be done**: Gain meaningful knowledge, find resonance with personal experiences, understand complex topics (medical/technical) in approachable terms. + +### Brand Personality + +- **Voice**: Reflective, professional, and thoughtful—like a trusted physician who also happens to be a developer +- **3-word personality**: Professional & refined, Thoughtful & reflective, Technical & practical, Approachable & human +- **Emotional goals**: Calm & contemplative, Inspired & curious + +**Not**: Corporate, salesy, alarmist (like news sites), or overly technical/clinical. + +### Aesthetic Direction + +**Visual tone**: Warm & organic with academic & scholarly sensibility, combined with modern technical clarity + +**References**: +- Medium (medium.com): Readability-focused, minimal distractions, clean typography +- Personal tech blogs: Individual personality, character, and hands-on authenticity +- Library aesthetic: Quiet, thoughtful, knowledge-rich environment + +**Anti-references** (explicitly avoid): +- News sites: Cluttered, headline-focused, clickbait design +- Social media feeds: Infinite scroll, attention-grabbing tactics, dopamine-driven design +- Corporate/SaaS: Too polished, salesy, or uniform corporate branding +- Dry technical docs: Lacking personality, purely functional + +**Theme**: Both light and dark modes equally important—light for daytime readability, dark for late-night focused reading. Accent colors should be warm (avoid reds/yellows which feel urgent/alerting). + +### Design Principles + +1. **Calm-first design**: Space, breathing room, and typography hierarchy should prioritize relaxed reading over visual stimulation. Avoid jarring transitions or animation that distracts from content. + +2. **Warm technicality**: Blend technical precision with human warmth—clean, efficient interfaces that don't feel cold or sterile. The HomeLab/developer content should feel hands-on, not just theoretical. + +3. **Academic elegance**: Typography and layout should honor the scholarly nature of medical writing and technical explanations—clear hierarchy, proper spacing, and readability first. + +4. **Inclusive accessibility**: Consider hearing/vision impairments (user has Usher syndrome): high contrast, readable text, motion sensitivity support, clear navigation, and no time-based content hiding. + +5. **Consistent rhythm**: Maintain consistent spacing, sizing, and interaction patterns across pages to create a predictable, trustworthy experience. Subtle interactions > flashy animations. diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index ba3ae9c..793f300 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { Link } from 'next-view-transitions'; +import Link from 'next/link'; import Image from 'next/image'; import { notFound } from 'next/navigation'; import type { Metadata } from 'next'; @@ -222,7 +222,7 @@ export default async function BlogPostPage({ params }: Props) { href={`/tags/${encodeURIComponent( t.toLowerCase().replace(/\s+/g, '-') )}`} - className="tag-chip rounded-full bg-accent-soft px-3 py-1 text-sm text-accent-textLight dark:bg-slate-800 dark:text-slate-100" + className="tag-chip rounded-full bg-accent-soft px-3 py-1 text-sm text-accent-textLight dark:bg-slate-800 dark:text-slate-100 dark:hover:bg-slate-700 dark:hover:text-white" > #{t} diff --git a/app/blog/page.tsx b/app/blog/page.tsx index 148c4d3..a3f29d0 100644 --- a/app/blog/page.tsx +++ b/app/blog/page.tsx @@ -1,4 +1,4 @@ -import { Link } from 'next-view-transitions'; +import Link from 'next/link'; import { getAllPostsSorted } from '@/lib/posts'; import { PostListWithControls } from '@/components/post-list-with-controls'; import { TimelineWrapper } from '@/components/timeline-wrapper'; diff --git a/app/layout.tsx b/app/layout.tsx index 22cb7ad..cb71124 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -7,7 +7,7 @@ import { ThemeProvider } from 'next-themes'; import { Playfair_Display, LXGW_WenKai_TC } from 'next/font/google'; import { JsonLd } from '@/components/json-ld'; import { WebVitals } from '@/components/web-vitals'; -import { ViewTransitions } from 'next-view-transitions'; +import { ViewTransitionProvider } from '@/components/view-transition-provider'; import NextTopLoader from 'nextjs-toploader'; const playfair = Playfair_Display({ @@ -17,12 +17,12 @@ const playfair = Playfair_Display({ }); const lxgwWenKai = LXGW_WenKai_TC({ - weight: ['400', '700'], // 只加载 Regular 和 Bold + weight: ['400', '700'], subsets: ['latin'], variable: '--font-serif-cn', display: 'swap', preload: true, - adjustFontFallback: false, // 中文字体不需要 fallback 调整,使用系统字体作为 fallback + adjustFontFallback: false, }); export const metadata: Metadata = { @@ -88,7 +88,6 @@ export default async function RootLayout({ .slice(0, 5) .map((p) => ({ title: p.title, url: p.url })); - // WebSite Schema const websiteSchema = { '@context': 'https://schema.org', '@type': 'WebSite', @@ -111,7 +110,6 @@ export default async function RootLayout({ }, }; - // Organization Schema const organizationSchema = { '@context': 'https://schema.org', '@type': 'Organization', @@ -125,28 +123,27 @@ export default async function RootLayout({ ].filter(Boolean), }; + + return ( - - - - {/* Preconnect to Google Fonts for faster font loading */} - - - - - - - -