Han's Portfolio Live
A modern, multilingual portfolio website built with Astro, React, and Tailwind CSS. Features smooth transitions with the View Transition API, full site search with PageFind, content management for articles and projects, and certification showcase.
- Internationalization (i18n): Supports English (
en) and Taiwanese Mandarin (tw) locales, managed viasrc/lib/i18n.tsand Astro's i18n routing. - Content Collections: Manages articles, projects, certifications, and organizations using Astro's content collections (see
src/content.config.ts).- Articles and Projects are written in Markdown.
- Certifications and Organizations data is loaded from JSON files.
- Pagefind Integration: Provides client-side search functionality (see
astro.config.ts). - Sitemap Generation: Automatically generates a sitemap (see
astro.config.ts). - RSS Feed: Generates an RSS feed for articles.
- Partytown Integration: Offloads third-party scripts to a web worker for improved performance.
- Image Optimization: Uses Astro's built-in image optimization.
- Dark Mode: Supports light and dark themes with system preference detection.
- View Transitions: Utilizes the View Transitions API for smooth page navigation with optimized performance architecture.
- Employs Astro's
<ClientRouter />and dynamically assignedview-transition-names to optimize performance and prevent conflicts across various UI transitions, including theme switching, lightbox popovers, navigation menus, page-to-page navigation, and list-to-list/detail views.
- Employs Astro's
- SEO Friendly: Includes meta tags, Open Graph tags, and structured data for better search engine visibility.
- Custom Fonts: Uses Google Fonts (Inter) via Astro's font configuration.
- Markdown Enhancements:
rehype-image-caption: Adds captions to images in Markdown.rehype-lightbox: Adds a lightbox effect to images (seesrc/lib/rehype-lightbox.ts).
- Utility Scripts:
extract-cert-data.js: Extracts unique names, organizations, or skills fromcertifications.json(seeutil/extract-cert-data.js).slugify-cli.js: A CLI tool to slugify strings (seeutil/slugify-cli.js).
- Framework: Astro
- Frontend Library: React
- Component Library: Shadcn
- Language: TypeScript
- Styling: Tailwind CSS
- Deployment: Cloudflare Pages
- Icons: Lucide React, Astro Icon
- Forms: React Hook Form with Zod resolver
- Search: Pagefind
- Content: Markdown processing with rehype plugins
- Internationalization: Astro i18n
portfolio/
βββ public/ # Static assets
βββ src/
β βββ assets/ # Images, icons, etc.
β βββ components/ # Reusable Astro/React components
β β βββ ui/ # Shadcn UI components
β β βββ ArticleCard.astro
β β βββ ProjectCard.astro
β β βββ CertificationCard.astro
β β βββ ...
β βββ layouts/ # Base layout for pages
β βββ pages/ # Route pages
β β βββ [...locale]/ # Internationalized routes
β βββ lib/ # Utilities and configurations
β β βββ i18n/ # Internationalization data
β β βββ i18n.ts # i18n utilities
β β βββ nav.ts # Navigation configuration
β β βββ utils.ts # Helper functions
β βββ styles/ # Global CSS
β βββ content.config.ts # Content collections schema
β βββ articles/ # Blog articles and assets (Markdown)
β βββ projects/ # Project descriptions and assets (Markdown)
β βββ certifications/ # Certification data and assets (JSON)
β βββ organizations/ # Brand data and assets (JSON)
βββ util/ # Utility scripts
βββ astro.config.ts # Astro configuration
βββ content.config.ts # Astro content collections configuration
βββ package.json # Project dependencies and scripts
βββ tsconfig.json # TypeScript configuration
βββ wrangler.toml # Cloudflare Pages configuration
The project uses Astro's content collections for structured content management:
- Articles: Blog posts with frontmatter, tags, categories, and change logs
- Projects: Portfolio projects with tech stacks, links, and sidebar cards
- Certifications: Professional certifications with badges and verification links
- Organizations: Brands/organization information with icons and logos
Supports English (en) and Taiwanese Mandarin (tw) with:
- Locale configuration is in
src/lib/i18n.ts. - Astro's i18n routing is used, with language prefixes in URLs (e.g.,
/en/about,/tw/about). The default locale (en) does not require a prefix./en/*and/*default routes are served in English/tw/*routes are served in Taiwanese Mandarin
- Translations for UI elements are stored in
src/lib/i18n/ui.ts(and similar files for categories, tags, skills). - Localized content for Articles and Projects are stored in
en/andtw/folders- The same article in different languages should have the same markdown filename
- URL slugs are generated from the markdown filenames
- Date formatting and stop word filtering
The portfolio implements a sophisticated view transitions system using Astro's astro:transitions with <ClientRouter /> and dynamic view-transition-name assignment for optimal performance and seamless user experience:
- Dynamic Transition Names: Uses programmatically assigned
view-transition-nameattributes to avoid interference between different transition types - Fallback Support: Respects
reduced-motionOS settings and graceful fallback for browsers that don't support view transitions API.
- Theme Switching: Smooth light/dark mode transitions without visual disruption
- Lightbox Popovers: Image gallery interactions with fluid open/close animations
- Navigation Menu: Menu state changes with contextual transitions
- Page-to-Page Navigation: Cross-route MPA transitions maintaining visual continuity
- List-to-List Views: Seamless filtering transitions (e.g., certification filters, project categories)
- List-to-Detail Views: Smooth navigation from overview pages to detailed content with shared element morphing
- Node.js 22+
- npm
- Clone the repository:
git clone https://github.com/hotdogee/portfolio
cd portfolio- Install dependencies:
npm i- Build the search index:
npm run build- Start the development server:
npm run dev- Open http://localhost:4321 in your browser
npm run dev: Starts the development server.npm run build: Builds the project for production.npm run preview: Previews the production build locally.npm run astro: Accesses the Astro CLI.npm run extract-certs <field> [options]: Extracts unique data fromcertifications.json.- Fields:
name,organization,skills - Options:
--count(or-c),--json(or-j) - Example:
npm run extract-certs skills -- --json
- Fields:
npm run slugify "<text>" [options]: Slugifies the given text.- Options:
--keep-stop-words(or-k) - Example:
npm run slugify "My Awesome Project" -- --keep-stop-words
- Options:
Schema defined in src/content.config.ts.
Articles: Create .md files in src/articles/ with frontmatter:
Assets like images can be colocated in a project folder with the markdown filename the same as the project folder name. Folders are not required if your project doesn't have any assets or if your assets are all served from a Digital Asset Management like Cloudinary.
---
title: 'Article Title'
excerpt: 'Brief description'
author: 'Author Name'
categories: ['category1', 'category2']
tags: ['tag1', 'tag2']
changes:
- '2025-01-01': 'Initial post'
---Projects: Create .md files in src/projects/ with frontmatter:
Assets like images can be colocated in a project folder with the markdown filename the same as the project folder name. Folders are not required if your project doesn't have any assets or if your assets are all served from a Digital Asset Management like Cloudinary.
---
title: 'Project Name'
tagline: 'Brief description'
tech: ['React', 'TypeScript']
featured: 1
categories: ['Web Development']
links:
- text: 'Live Demo'
url: 'https://example.com'
icon: 'lucide:external-link'
changes:
- '2025-01-01': 'Project completed'
---Certifications: Data stored in src/certifications/certifications.json.
Organizations: Data stored in src/organizations/organizations.json.
- Tailwind CSS classes for styling
- Custom CSS variables for themes
- Component-based architecture with Astro and React
The project is configured for deployment on Cloudflare Pages.
The wrangler.toml file contains basic Cloudflare Pages configuration.
The build output directory is ./dist.
The build command npm run build creates a production-ready static site.
Cloudflare Pages specific build format (format: 'file') is set in astro.config.ts to handle trailing slashes correctly.
A fix for React 19 on Cloudflare is also included in the Vite configuration within astro.config.ts.
- Astro Configuration:
astro.config.ts- Contains site settings, integrations, Markdown processing, Vite configurations, and i18n setup. - Content Collections:
src/content.config.ts- Defines schemas for articles, projects, certifications, and organizations. - TypeScript:
tsconfig.json- Configures TypeScript compiler options and path aliases. - Environment Variables:
SHOW_DOWNLOAD_CV: (boolean, optional, default:false) - Controls the visibility of the "Download CV" button. Defined inastro.config.ts.
- Prettier: Code formatting with plugin support
- TypeScript: Type checking and IntelliSense
- Vite: Fast development and building
- ESLint: Code linting (via Astro config)
This project is open source and available under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request.
For questions or suggestions, please reach out through the contact form on the website.


