A modern, minimalist personal landing page theme built with Astro 5
Features • Quick Start • Configuration • Customization
| Feature | Description |
|---|---|
| Internationalization | Built-in internationalization with Astro's native i18n routing and Content Collections |
| Dark Mode | Automatic theme switching with system preference detection and localStorage persistence |
| Responsive Design | Mobile-first design that looks great on all devices |
| RSS Aggregation | Fetch and display posts from external RSS/Atom feeds |
| Contact Form | Pre-configured EmailJS integration for functional contact forms |
| Analytics | Optional Google Analytics 4 integration |
| Islands Architecture | React components loaded on demand, minimizing JS bundle size |
# Clone the template
git clone https://github.com/WayneXuCN/starter-theme.git my-site
cd my-site
# Install dependencies
bun install
# Start development server
bun run devOpen http://localhost:4321 to see your site.
bun run buildOutput is generated in the dist/ directory, ready for deployment to any static hosting platform.
src/
├── components/
│ ├── react/ # React Islands
│ │ ├── Contact.jsx
│ │ ├── ErrorBoundary.jsx
│ │ ├── HeaderBar.jsx
│ │ ├── LanguageSwitcher.jsx
│ │ ├── PrimaryNav.jsx
│ │ ├── ThemeToggle.jsx
│ │ └── UnderlineEffects.jsx
│ │
│ └── ui/ # Astro 组件
│ ├── Hero.astro
│ ├── Footer.astro
│ ├── WebsiteItem.astro
│ ├── WebsitesSection.astro
│ ├── FeaturedPostItem.astro
│ └── FeaturedPostsSection.astro
│
├── layouts/
│ └── BaseLayout.astro # 全局布局
│
├── lib/
│ ├── i18n.ts # i18n 工具函数
│ └── utils.ts # 公共工具函数
│
├── pages/
│ ├── index.astro # 根首页
│ ├── 404.astro # 根 404
│ └── [lang]/ # 动态路由
│ ├── index.astro
│ ├── about.astro
│ ├── contact.astro
│ └── 404.astro
│
└── styles/
└── global.css # 全局样式
Create a .env file in the project root:
# EmailJS (required for contact form)
PUBLIC_EMAILJS_SERVICE_ID=your_service_id
PUBLIC_EMAILJS_TEMPLATE_ID=your_template_id
PUBLIC_EMAILJS_PUBLIC_KEY=your_public_key
# Google Analytics (optional)
PUBLIC_GA_ID=G-XXXXXXXXXXEdit astro.config.mjs to update your site URL:
export default defineConfig({
site: 'https://your-domain.com',
// ...
});All site content is managed through JSON files in src/content/i18n/:
| File | Description |
|---|---|
zh_CN.json |
Chinese content |
en_US.json |
English content |
Each file contains:
{
"site": { "title": "...", "description": "...", "author": "..." },
"nav": [{ "label": "Home", "href": "index.html" }],
"header": { "name": "...", "avatar": "..." },
"hero": { "title": "...", "subtitle": "...", "description": "..." },
"websites": { "title": "...", "items": [...] },
"featuredPosts": { "title": "...", "rss": {...}, "items": [...] },
"footer": { "copyright": "...", "socialLinks": [...] },
"about": { ... },
"contact": { ... }
}Configure RSS aggregation in your locale JSON:
{
"featuredPosts": {
"rss": {
"enabled": true,
"feeds": [
{ "url": "https://blog.example.com/feed.xml", "parser": "default" }
],
"limit": 6
}
}
}The project supports 2 languages by default (Chinese and English). To add a new language, follow these steps:
-
Update Astro configuration (
astro.config.mjs):// In the i18n section, add your new locale code i18n: { defaultLocale: 'zh_CN', locales: ['zh_CN', 'en_US', 'NEW_LOCALE'], // Add your new locale code here routing: { prefixDefaultLocale: true, redirectToDefaultLocale: false, }, },
Also update the sitemap i18n configuration:
sitemap({ i18n: { defaultLocale: 'zh_CN', locales: { zh_CN: 'zh-CN', en_US: 'en-US', // ... existing locales locales: { zh_CN: 'zh-CN', en_US: 'en-US', NEW_LOCALE: 'new-locale', // Add your new locale mapping }, }, }, }),
-
Update i18n utilities (
src/lib/i18n.ts):// Add to the locales array export const locales = ['zh_CN', 'en_US', 'NEW_LOCALE'] as const; // Add to the localeConfig object export const localeConfig: Record<Locale, { label: string; name: string; hrefLang: string }> = { // ... existing locales NEW_LOCALE: { label: 'XX', // Short label (1-3 characters) name: 'Language Name', // Full language name hrefLang: 'new-locale', // BCP 47 language tag }, };
-
Create translation file (
i18n/NEW_LOCALE.json):Copy an existing translation file (e.g.,
en_US.json) and translate all content. The file should follow this structure:{ "site": { "title": "Your Site Title", "description": "Your site description", "author": "Your Name" }, "nav": [ { "label": "Home", "href": "index.html" }, { "label": "About", "href": "about.html" }, { "label": "Contact", "href": "contact.html" } ], "header": { "name": "Your Name", "avatar": "/assets/img/prof_pic.png" }, "hero": { "title": "Welcome to My Site", "subtitle": "Your Subtitle", "description": "Your description text..." }, // ... translate all other sections } -
Create page routes (
src/pages/NEW_LOCALE/):Copy the existing language file (e.g.,
i18n/en_US.json) and rename it to your new locale code (e.g.,i18n/NEW_LOCALE.json). Update any hardcoded text in the.astrofiles. -
Update content configuration (
src/content.config.ts):The content configuration automatically supports new locales through the
i18ncollection schema. No changes are needed here.
- Use
ISO 639-1language code +ISO 3166-1 alpha-2country code format (e.g.,en_US,zh_CN) - For languages without country-specific variants, use just the language code (e.g.,
esfor Spanish) - Ensure the locale code matches exactly across all configuration files
-
Complete Translation: Translate all sections in the JSON file, including navigation, hero, websites, featured posts, about, contact, and footer.
-
Test Navigation: Verify the language switcher works correctly with your new locale.
-
SEO Considerations: Ensure
hrefLangvalues follow BCP 47 format for proper SEO. -
RTL Support: For right-to-left languages (like Arabic), update the layout direction in
BaseLayout.astro:<html lang={locale} dir={locale === 'ar_SA' ? 'rtl' : 'ltr'}>
-
Font Support: Add appropriate font imports in
src/styles/global.cssif needed for non-Latin scripts.
- Colors & Theme: Edit
tailwind.config.mjs - Global Styles: Edit
src/styles/global.css - Dark Mode: Use Tailwind's
dark:prefix
All interactive components are React islands in src/components/react/:
| Component | Purpose |
|---|---|
HeaderBar.jsx |
Navigation with language switcher |
HeaderBar.jsx |
Navigation with language switcher |
Contact.jsx |
Contact page with form |
ErrorBoundary.jsx |
Error boundary for React components |
LanguageSwitcher.jsx |
Language selector |
PrimaryNav.jsx |
Primary navigation |
ThemeToggle.jsx |
Dark/light mode toggle |
UnderlineEffects.jsx |
Underline hover effects |
The theme generates static HTML files that can be deployed anywhere:
npx vercelnpx netlify deploy --prod --dir=distUse the included GitHub Actions workflow or deploy manually:
bun run build
# Upload dist/ to gh-pages branchConnect your repository and set:
- Build command:
bun run build - Output directory:
dist
| Command | Description |
|---|---|
bun run dev |
Start development server |
bun run build |
Build for production |
bun run preview |
Preview production build |
bun run fetch:rss |
Fetch RSS feeds |
bun run format |
Format code with Prettier |
- Framework: Astro 5.x
- UI: React 19.x
- Styling: Tailwind CSS 3.x
- Runtime: Bun 1.x
- Email: EmailJS
Contributions are welcome! Please read our Contributing Guide before submitting a PR.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
Made with love by Wenjie Xu
