@jet-w/astro-blog 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-HVQKQN6B.js → chunk-6D3XRDNY.js} +1 -1
- package/dist/{chunk-ATRISB7B.js → chunk-A2E2VSAQ.js} +43 -3
- package/dist/{chunk-AZHCNNAC.js → chunk-TJTPX2WP.js} +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +2 -2
- package/dist/{i18n-5H4W145i.d.ts → i18n-PgMCFBw0.d.ts} +20 -0
- package/dist/index.d.ts +21 -3
- package/dist/index.js +20 -3
- package/dist/integration.d.ts +1 -1
- package/dist/integration.js +2 -2
- package/package.json +1 -1
- package/src/components/blog/FloatingToc.vue +11 -3
- package/src/components/blog/Hero.astro +17 -2
- package/src/components/blog/NavigationTabs.vue +46 -15
- package/src/components/blog/PostCard.astro +28 -10
- package/src/components/blog/RelatedPosts.astro +23 -7
- package/src/components/blog/TableOfContents.astro +10 -4
- package/src/components/blog/TagCloud.astro +4 -3
- package/src/components/home/FeaturedPostsSection.astro +22 -6
- package/src/components/home/QuickNavSection.astro +33 -4
- package/src/components/home/RecentPostsSection.astro +22 -6
- package/src/components/home/StatsSection.astro +24 -6
- package/src/components/layout/Header.astro +9 -5
- package/src/components/layout/Sidebar.astro +14 -11
- package/src/components/ui/SearchBox.vue +13 -5
- package/src/components/ui/SearchInterface.vue +49 -25
- package/src/pages/archives/[year]/[month].astro +36 -17
- package/src/pages/archives/index.astro +36 -20
- package/src/pages/categories/[category].astro +33 -16
- package/src/pages/categories/index.astro +37 -14
- package/src/pages/posts/[...slug].astro +125 -18
- package/src/pages/posts/index.astro +59 -37
- package/src/pages/posts/page/[page].astro +65 -27
- package/src/pages/search.astro +50 -14
- package/src/pages/slides/index.astro +25 -6
- package/src/pages/tags/[tag].astro +32 -15
- package/src/pages/tags/index.astro +39 -16
- package/src/plugins/remark-containers.mjs +351 -322
- package/src/plugins/remark-protect-code.mjs +69 -0
- package/src/styles/global.css +35 -1
- package/templates/default/.claude/ralph-loop.local.md +48 -0
- package/templates/default/astro.config.mjs +13 -4
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/01-intro.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/02-install.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/03-create-post.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/04-structure.md +1 -1
- package/templates/default/content/posts/blog_docs_en/01.get-started/05-deploy.md +208 -0
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/README.md +1 -1
- package/templates/default/content/posts/blog_docs_en/02.guide/02-containers.md +245 -0
- package/templates/default/content/posts/blog_docs_en/{guide/markdown → 02.guide}/03-code-blocks.md +2 -1
- package/templates/default/content/posts/blog_docs_en/{guide/features/01-mermaid.md → 02.guide/03-mermaid.md} +1 -1
- package/templates/default/content/posts/blog_docs_en/{guide/features → 02.guide}/04-icons.md +4 -2
- package/templates/default/content/posts/blog_docs_en/{guide/features/02-latex.md → 02.guide/06-latex.md} +1 -1
- package/templates/default/content/posts/blog_docs_en/{guide/features/03-video.md → 02.guide/07-video.md} +1 -1
- package/templates/default/content/posts/blog_docs_en/02.guide/08-slides.md +359 -0
- package/templates/default/content/posts/blog_docs_en/{guide/markdown → 02.guide}/README.md +22 -3
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/01-site.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/02-sidebar.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/03-i18n.md +88 -24
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/README.md +1 -1
- package/templates/default/content/posts/blog_docs_en/README.md +2 -1
- package/templates/default/content/posts/blog_docs_zh/01.get-started/01-intro.md +81 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/02-install.md +137 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/03-create-post.md +176 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/04-structure.md +173 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/05-deploy.md +208 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/README.md +52 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/02-containers.md +245 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/03-code-blocks.md +206 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/03-mermaid.md +194 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/04-icons.md +229 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/06-latex.md +233 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/07-video.md +184 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/08-slides.md +359 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/README.md +213 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/01-site.md +208 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/02-sidebar.md +240 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/03-i18n.md +348 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/README.md +85 -0
- package/templates/default/content/posts/blog_docs_zh/README.md +78 -0
- package/templates/default/src/config/locales/en/index.ts +5 -1
- package/templates/default/src/config/locales/en/menu.ts +3 -1
- package/templates/default/src/config/locales/en/sidebar.ts +18 -2
- package/templates/default/src/config/locales/en/site.ts +1 -1
- package/templates/default/src/config/locales/en/ui.ts +29 -0
- package/templates/default/src/config/locales/zh-CN/index.ts +5 -1
- package/templates/default/src/config/locales/zh-CN/menu.ts +7 -5
- package/templates/default/src/config/locales/zh-CN/sidebar.ts +22 -6
- package/templates/default/src/config/locales/zh-CN/site.ts +2 -2
- package/templates/default/src/config/locales/zh-CN/ui.ts +29 -0
- package/templates/default/src/config/site.ts +2 -2
- package/templates/default/src/content.config.ts +15 -3
- package/templates/default/content/posts/blog_docs/01-quick-start.md +0 -162
- package/templates/default/content/posts/blog_docs/02-frontmatter.md +0 -277
- package/templates/default/content/posts/blog_docs/03-markdown-basic.md +0 -350
- package/templates/default/content/posts/blog_docs/04-containers.md +0 -331
- package/templates/default/content/posts/blog_docs/05-code-blocks.md +0 -388
- package/templates/default/content/posts/blog_docs/06-mermaid.md +0 -431
- package/templates/default/content/posts/blog_docs/07-video.md +0 -243
- package/templates/default/content/posts/blog_docs/08-latex.md +0 -382
- package/templates/default/content/posts/blog_docs/09-icons.md +0 -326
- package/templates/default/content/posts/blog_docs/10-sidebar.md +0 -445
- package/templates/default/content/posts/blog_docs/11-config.md +0 -334
- package/templates/default/content/posts/blog_docs/12-i18n.md +0 -355
- package/templates/default/content/posts/blog_docs/12-slides.mdx +0 -552
- package/templates/default/content/posts/blog_docs/README.md +0 -152
- package/templates/default/content/posts/blog_docs_en/get-started/05-deploy.md +0 -197
- package/templates/default/content/posts/blog_docs_en/guide/README.md +0 -59
- package/templates/default/content/posts/blog_docs_en/guide/features/README.md +0 -51
- package/templates/default/content/posts/blog_docs_en/guide/markdown/02-containers.md +0 -226
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remark plugin to protect code blocks from directive processing
|
|
3
|
+
* This plugin runs BEFORE other plugins to replace ::: in code blocks
|
|
4
|
+
* with a placeholder, then a rehype plugin restores them after processing
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Unique placeholder that won't appear in normal content
|
|
8
|
+
const COLON_PLACEHOLDER = '___TRIPLE_COLON___';
|
|
9
|
+
|
|
10
|
+
export function remarkProtectCode() {
|
|
11
|
+
return (tree) => {
|
|
12
|
+
// Visit all code nodes and replace ::: with placeholder
|
|
13
|
+
visitCode(tree);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function visitCode(node) {
|
|
18
|
+
if (node.type === 'code' && node.value) {
|
|
19
|
+
// Replace all ::: patterns in code blocks with placeholder
|
|
20
|
+
node.value = node.value.replace(/:::/g, COLON_PLACEHOLDER);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Recursively visit children
|
|
24
|
+
if (node.children) {
|
|
25
|
+
for (const child of node.children) {
|
|
26
|
+
visitCode(child);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Rehype plugin to restore ::: in code blocks after directive processing
|
|
33
|
+
*/
|
|
34
|
+
export function rehypeRestoreCode() {
|
|
35
|
+
return (tree) => {
|
|
36
|
+
visitElement(tree);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function visitElement(node) {
|
|
41
|
+
// Handle text nodes
|
|
42
|
+
if (node.type === 'text' && node.value) {
|
|
43
|
+
node.value = node.value.replace(new RegExp(COLON_PLACEHOLDER, 'g'), ':::');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Handle raw HTML nodes
|
|
47
|
+
if (node.type === 'raw' && node.value) {
|
|
48
|
+
node.value = node.value.replace(new RegExp(COLON_PLACEHOLDER, 'g'), ':::');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Handle element nodes with properties (like code elements)
|
|
52
|
+
if (node.type === 'element') {
|
|
53
|
+
// Check for text content in code elements
|
|
54
|
+
if (node.children) {
|
|
55
|
+
for (const child of node.children) {
|
|
56
|
+
visitElement(child);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Recursively visit children
|
|
62
|
+
if (node.children) {
|
|
63
|
+
for (const child of node.children) {
|
|
64
|
+
visitElement(child);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { COLON_PLACEHOLDER };
|
package/src/styles/global.css
CHANGED
|
@@ -248,13 +248,47 @@
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
.container-details .container-title {
|
|
251
|
-
@apply text-purple-800 dark:text-purple-200 bg-purple-100 dark:bg-purple-800/30;
|
|
251
|
+
@apply text-purple-800 dark:text-purple-200 bg-purple-100 dark:bg-purple-800/30 cursor-pointer select-none;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
.container-details .container-content {
|
|
255
255
|
@apply text-purple-700 dark:text-purple-300;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
+
/* details 展开/折叠图标 */
|
|
259
|
+
.container-details > summary.container-title {
|
|
260
|
+
@apply list-none relative pr-8;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* 移除默认的三角形图标 (Safari) */
|
|
264
|
+
.container-details > summary.container-title::-webkit-details-marker {
|
|
265
|
+
display: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* 自定义展开/折叠箭头图标 */
|
|
269
|
+
.container-details > summary.container-title::after {
|
|
270
|
+
content: '';
|
|
271
|
+
@apply absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 transition-transform duration-200;
|
|
272
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%237c3aed' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");
|
|
273
|
+
background-size: contain;
|
|
274
|
+
background-repeat: no-repeat;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/* 深色模式下的箭头颜色 */
|
|
278
|
+
.dark .container-details > summary.container-title::after {
|
|
279
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23c4b5fd' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* 展开状态时旋转箭头 */
|
|
283
|
+
.container-details[open] > summary.container-title::after {
|
|
284
|
+
transform: translateY(-50%) rotate(90deg);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* 悬停效果 */
|
|
288
|
+
.container-details > summary.container-title:hover {
|
|
289
|
+
@apply bg-purple-200 dark:bg-purple-700/40;
|
|
290
|
+
}
|
|
291
|
+
|
|
258
292
|
/* 容器内的段落样式 */
|
|
259
293
|
.custom-container .container-content p {
|
|
260
294
|
@apply mb-3 last:mb-0;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
active: false
|
|
3
|
+
iteration: 2
|
|
4
|
+
max_iterations: 20
|
|
5
|
+
completion_promise: "DONE"
|
|
6
|
+
started_at: "2026-01-29T01:25:08Z"
|
|
7
|
+
completed_at: "2026-01-29T01:48:00Z"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
DONE
|
|
11
|
+
|
|
12
|
+
## Issue Fixed
|
|
13
|
+
|
|
14
|
+
The i18n URL routing and navigation link issue has been resolved.
|
|
15
|
+
|
|
16
|
+
### Root Cause Analysis
|
|
17
|
+
|
|
18
|
+
When English is set as the default locale with `prefixDefaultLocale: false`:
|
|
19
|
+
- English pages use URLs without prefix: `/posts/...`
|
|
20
|
+
- Chinese pages should use URLs with prefix: `/zh-CN/posts/...`
|
|
21
|
+
|
|
22
|
+
However, the navigation menu and sidebar tree links in the zh-CN locale config were missing the `/zh-CN/` prefix, causing navigation links to point to the wrong locale.
|
|
23
|
+
|
|
24
|
+
### Files Modified
|
|
25
|
+
|
|
26
|
+
1. **`templates/default/src/config/locales/zh-CN/menu.ts`**
|
|
27
|
+
- Updated all menu links to include `/zh-CN/` prefix
|
|
28
|
+
- Changed `href: '/'` to `href: '/zh-CN/'`
|
|
29
|
+
- Changed `href: '/posts/...'` to `href: '/zh-CN/posts/...'`
|
|
30
|
+
- Changed `href: '/slides'` to `href: '/zh-CN/slides'`
|
|
31
|
+
- Changed `href: '/about'` to `href: '/zh-CN/about'`
|
|
32
|
+
|
|
33
|
+
2. **`templates/default/src/config/locales/zh-CN/sidebar.ts`**
|
|
34
|
+
- Updated sidebar group titles to Chinese: '快速入门', '使用指南', '配置文档'
|
|
35
|
+
- Updated comments to Chinese
|
|
36
|
+
|
|
37
|
+
3. **`src/components/layout/Sidebar.astro`**
|
|
38
|
+
- Fixed all tree links to use `${localePrefix}/posts/...` instead of hardcoded `/posts/...`
|
|
39
|
+
- This ensures sidebar tree navigation respects the current locale
|
|
40
|
+
|
|
41
|
+
### URL Behavior (Correct)
|
|
42
|
+
|
|
43
|
+
| Language | URL Pattern |
|
|
44
|
+
|----------|-------------|
|
|
45
|
+
| English (default) | `/posts/...`, `/slides`, `/about` |
|
|
46
|
+
| Chinese | `/zh-CN/posts/...`, `/zh-CN/slides`, `/zh-CN/about` |
|
|
47
|
+
|
|
48
|
+
This is the expected behavior with `prefixDefaultLocale: false`.
|
|
@@ -9,6 +9,7 @@ import rehypeRaw from 'rehype-raw';
|
|
|
9
9
|
|
|
10
10
|
// Import plugins and integration from @jet-w/astro-blog
|
|
11
11
|
import { astroBlog, defineI18nConfig } from '@jet-w/astro-blog';
|
|
12
|
+
import { remarkProtectCode, rehypeRestoreCode } from '@jet-w/astro-blog/plugins/remark-protect-code.mjs';
|
|
12
13
|
import { remarkContainers } from '@jet-w/astro-blog/plugins/remark-containers.mjs';
|
|
13
14
|
import { remarkMermaid } from '@jet-w/astro-blog/plugins/remark-mermaid.mjs';
|
|
14
15
|
import { rehypeCleanContainers } from '@jet-w/astro-blog/plugins/rehype-clean-containers.mjs';
|
|
@@ -23,15 +24,15 @@ import { enConfig } from './src/config/locales/en';
|
|
|
23
24
|
const i18nConfig = defineI18nConfig({
|
|
24
25
|
defaultLocale: 'en',
|
|
25
26
|
locales: [
|
|
26
|
-
{ code: 'zh-CN', name: '中文', htmlLang: 'zh-CN', dateLocale: 'zh-CN' },
|
|
27
27
|
{ code: 'en', name: 'English', htmlLang: 'en', dateLocale: 'en-US' },
|
|
28
|
+
{ code: 'zh-CN', name: '中文', htmlLang: 'zh-CN', dateLocale: 'zh-CN' },
|
|
28
29
|
],
|
|
29
30
|
routing: {
|
|
30
31
|
prefixDefaultLocale: false, // en (default) uses /posts, zh-CN uses /zh-CN/posts
|
|
31
32
|
},
|
|
32
33
|
localeConfigs: {
|
|
33
|
-
'zh-CN': zhCNConfig,
|
|
34
34
|
'en': enConfig,
|
|
35
|
+
'zh-CN': zhCNConfig,
|
|
35
36
|
},
|
|
36
37
|
});
|
|
37
38
|
|
|
@@ -47,9 +48,10 @@ export default defineConfig({
|
|
|
47
48
|
],
|
|
48
49
|
markdown: {
|
|
49
50
|
remarkPlugins: [
|
|
50
|
-
|
|
51
|
+
remarkProtectCode, // Must run FIRST to protect code blocks
|
|
51
52
|
remarkMath,
|
|
52
|
-
|
|
53
|
+
remarkDirective, // Parse ::: syntax into directive nodes
|
|
54
|
+
remarkContainers, // Handle container syntax (works with both plain text and directive nodes)
|
|
53
55
|
remarkMermaid,
|
|
54
56
|
],
|
|
55
57
|
rehypePlugins: [
|
|
@@ -58,6 +60,7 @@ export default defineConfig({
|
|
|
58
60
|
rehypeCleanContainers,
|
|
59
61
|
rehypeTabs,
|
|
60
62
|
rehypeRelativeLinks,
|
|
63
|
+
rehypeRestoreCode, // Must run LAST to restore ::: in code blocks
|
|
61
64
|
],
|
|
62
65
|
shikiConfig: {
|
|
63
66
|
theme: 'github-dark',
|
|
@@ -69,5 +72,11 @@ export default defineConfig({
|
|
|
69
72
|
base: '/',
|
|
70
73
|
build: {
|
|
71
74
|
assets: 'assets'
|
|
75
|
+
},
|
|
76
|
+
vite: {
|
|
77
|
+
resolve: {
|
|
78
|
+
// Help Vite resolve peer dependencies from injected routes
|
|
79
|
+
dedupe: ['@astrojs/rss', 'astro']
|
|
80
|
+
}
|
|
72
81
|
}
|
|
73
82
|
});
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Deployment
|
|
3
|
+
description: Build and deploy your blog to GitHub Pages
|
|
4
|
+
pubDate: 2025-01-01
|
|
5
|
+
author: jet-w
|
|
6
|
+
categories:
|
|
7
|
+
- Documentation
|
|
8
|
+
tags:
|
|
9
|
+
- Getting Started
|
|
10
|
+
- Deployment
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Deployment
|
|
14
|
+
|
|
15
|
+
Time to share your blog with the world! This guide covers deploying to GitHub Pages.
|
|
16
|
+
|
|
17
|
+
## Build for Production
|
|
18
|
+
|
|
19
|
+
First, create a production build:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This creates a `dist/` folder with static files:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
dist/
|
|
29
|
+
├── index.html
|
|
30
|
+
├── posts/
|
|
31
|
+
│ └── hello-world/
|
|
32
|
+
│ └── index.html
|
|
33
|
+
├── assets/
|
|
34
|
+
│ ├── styles.css
|
|
35
|
+
│ └── scripts.js
|
|
36
|
+
└── ...
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Preview Locally
|
|
40
|
+
|
|
41
|
+
Test the build before deploying:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run preview
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Visit `http://localhost:4321` to verify everything works.
|
|
48
|
+
|
|
49
|
+
## Deploy to GitHub Pages
|
|
50
|
+
|
|
51
|
+
### Step 1: Configure Astro
|
|
52
|
+
|
|
53
|
+
Update your `astro.config.mjs`:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
import { defineConfig } from 'astro/config';
|
|
57
|
+
|
|
58
|
+
export default defineConfig({
|
|
59
|
+
site: 'https://username.github.io',
|
|
60
|
+
base: '/repo-name/', // Only if NOT using custom domain
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
::: tip Custom Domain
|
|
65
|
+
If using a custom domain (e.g., `myblog.com`), set `base: '/'` or remove it entirely.
|
|
66
|
+
:::
|
|
67
|
+
|
|
68
|
+
### Step 2: Create GitHub Actions Workflow
|
|
69
|
+
|
|
70
|
+
Create `.github/workflows/deploy.yml`:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
name: Deploy to GitHub Pages
|
|
74
|
+
|
|
75
|
+
on:
|
|
76
|
+
push:
|
|
77
|
+
branches: [main]
|
|
78
|
+
workflow_dispatch:
|
|
79
|
+
|
|
80
|
+
permissions:
|
|
81
|
+
contents: read
|
|
82
|
+
pages: write
|
|
83
|
+
id-token: write
|
|
84
|
+
|
|
85
|
+
concurrency:
|
|
86
|
+
group: "pages"
|
|
87
|
+
cancel-in-progress: false
|
|
88
|
+
|
|
89
|
+
jobs:
|
|
90
|
+
build:
|
|
91
|
+
runs-on: ubuntu-latest
|
|
92
|
+
steps:
|
|
93
|
+
- name: Checkout
|
|
94
|
+
uses: actions/checkout@v4
|
|
95
|
+
|
|
96
|
+
- name: Setup Node
|
|
97
|
+
uses: actions/setup-node@v4
|
|
98
|
+
with:
|
|
99
|
+
node-version: 20
|
|
100
|
+
cache: 'npm'
|
|
101
|
+
|
|
102
|
+
- name: Install dependencies
|
|
103
|
+
run: npm ci
|
|
104
|
+
|
|
105
|
+
- name: Build
|
|
106
|
+
run: npm run build
|
|
107
|
+
|
|
108
|
+
- name: Upload artifact
|
|
109
|
+
uses: actions/upload-pages-artifact@v3
|
|
110
|
+
with:
|
|
111
|
+
path: dist/
|
|
112
|
+
|
|
113
|
+
deploy:
|
|
114
|
+
needs: build
|
|
115
|
+
runs-on: ubuntu-latest
|
|
116
|
+
environment:
|
|
117
|
+
name: github-pages
|
|
118
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
119
|
+
steps:
|
|
120
|
+
- name: Deploy to GitHub Pages
|
|
121
|
+
id: deployment
|
|
122
|
+
uses: actions/deploy-pages@v4
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Step 3: Enable GitHub Pages
|
|
126
|
+
|
|
127
|
+
1. Go to your repository on GitHub
|
|
128
|
+
2. Navigate to **Settings** → **Pages**
|
|
129
|
+
3. Under "Build and deployment", select **GitHub Actions** as the source
|
|
130
|
+
4. Push your code to the `main` branch
|
|
131
|
+
|
|
132
|
+
Your site will be available at `https://username.github.io/repo-name/`
|
|
133
|
+
|
|
134
|
+
### Step 4: Custom Domain (Optional)
|
|
135
|
+
|
|
136
|
+
To use a custom domain:
|
|
137
|
+
|
|
138
|
+
1. **Add CNAME file**: Create `public/CNAME` with your domain:
|
|
139
|
+
```
|
|
140
|
+
myblog.com
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
2. **Configure DNS**: Add these records at your domain registrar:
|
|
144
|
+
- **A records** (for apex domain like `myblog.com`):
|
|
145
|
+
```
|
|
146
|
+
185.199.108.153
|
|
147
|
+
185.199.109.153
|
|
148
|
+
185.199.110.153
|
|
149
|
+
185.199.111.153
|
|
150
|
+
```
|
|
151
|
+
- **CNAME record** (for `www` subdomain):
|
|
152
|
+
```
|
|
153
|
+
www -> username.github.io
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
3. **Update Astro config**:
|
|
157
|
+
```javascript
|
|
158
|
+
export default defineConfig({
|
|
159
|
+
site: 'https://myblog.com',
|
|
160
|
+
// No base needed for custom domain
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
4. **Enable in GitHub**: In repository Settings → Pages, add your custom domain
|
|
165
|
+
|
|
166
|
+
::: info SSL Certificate
|
|
167
|
+
GitHub automatically provisions a free SSL certificate. It may take up to 24 hours.
|
|
168
|
+
:::
|
|
169
|
+
|
|
170
|
+
## Deployment Checklist
|
|
171
|
+
|
|
172
|
+
Before deploying, verify:
|
|
173
|
+
|
|
174
|
+
- [ ] `npm run build` completes without errors
|
|
175
|
+
- [ ] `npm run preview` shows site correctly
|
|
176
|
+
- [ ] All links work (no broken links)
|
|
177
|
+
- [ ] Images load properly
|
|
178
|
+
- [ ] Meta tags are set (title, description)
|
|
179
|
+
- [ ] Favicon is configured
|
|
180
|
+
|
|
181
|
+
## Continuous Deployment
|
|
182
|
+
|
|
183
|
+
Once configured, your site updates automatically:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
git add .
|
|
187
|
+
git commit -m "Add new blog post"
|
|
188
|
+
git push origin main
|
|
189
|
+
# Site automatically updates in ~1-2 minutes!
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Other Deployment Options
|
|
193
|
+
|
|
194
|
+
This blog can be deployed to any static hosting platform:
|
|
195
|
+
|
|
196
|
+
- **Vercel** - Zero-config Astro support, global CDN
|
|
197
|
+
- **Netlify** - Easy setup with form handling
|
|
198
|
+
- **Cloudflare Pages** - Fast edge network, free tier
|
|
199
|
+
- **AWS S3 + CloudFront** - Scalable cloud hosting
|
|
200
|
+
- **Firebase Hosting** - Google's hosting platform
|
|
201
|
+
|
|
202
|
+
For detailed instructions on these platforms, refer to the [Astro Deployment Guides](https://docs.astro.build/en/guides/deploy/).
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
Congratulations! You've completed the Get Started guide.
|
|
207
|
+
|
|
208
|
+
Continue learning with the [Writing Guide](/posts/blog_docs_en/02.guide) to master content creation.
|