@jet-w/astro-blog 0.1.6 → 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.
Files changed (122) hide show
  1. package/dist/chunk-6D3XRDNY.js +145 -0
  2. package/dist/chunk-A2E2VSAQ.js +246 -0
  3. package/dist/{chunk-GYLSY3OJ.js → chunk-TJTPX2WP.js} +1 -1
  4. package/dist/config/index.d.ts +3 -47
  5. package/dist/config/index.js +18 -2
  6. package/dist/i18n-PgMCFBw0.d.ts +222 -0
  7. package/dist/index.d.ts +204 -7
  8. package/dist/index.js +255 -3
  9. package/dist/integration.d.ts +9 -1
  10. package/dist/integration.js +2 -1
  11. package/dist/{sidebar-DNdiCKBw.d.ts → sidebar-Da-W_4Lr.d.ts} +1 -1
  12. package/dist/utils/sidebar.d.ts +1 -1
  13. package/package.json +1 -1
  14. package/src/components/blog/FloatingToc.vue +11 -3
  15. package/src/components/blog/Hero.astro +17 -2
  16. package/src/components/blog/NavigationTabs.vue +46 -15
  17. package/src/components/blog/PostCard.astro +28 -10
  18. package/src/components/blog/RelatedPosts.astro +23 -7
  19. package/src/components/blog/TableOfContents.astro +10 -4
  20. package/src/components/blog/TagCloud.astro +4 -3
  21. package/src/components/home/FeaturedPostsSection.astro +22 -6
  22. package/src/components/home/QuickNavSection.astro +33 -4
  23. package/src/components/home/RecentPostsSection.astro +22 -6
  24. package/src/components/home/StatsSection.astro +24 -6
  25. package/src/components/layout/Footer.astro +36 -20
  26. package/src/components/layout/Header.astro +75 -17
  27. package/src/components/layout/Sidebar.astro +40 -25
  28. package/src/components/ui/LanguageSwitcher.vue +183 -0
  29. package/src/components/ui/SearchBox.vue +13 -5
  30. package/src/components/ui/SearchInterface.vue +49 -25
  31. package/src/layouts/BaseLayout.astro +77 -52
  32. package/src/layouts/PageLayout.astro +22 -27
  33. package/src/layouts/SlidesLayout.astro +14 -2
  34. package/src/pages/archives/[year]/[month].astro +36 -17
  35. package/src/pages/archives/index.astro +36 -20
  36. package/src/pages/categories/[category].astro +33 -16
  37. package/src/pages/categories/index.astro +37 -14
  38. package/src/pages/posts/[...slug].astro +125 -18
  39. package/src/pages/posts/index.astro +59 -37
  40. package/src/pages/posts/page/[page].astro +65 -27
  41. package/src/pages/rss.xml.ts +18 -6
  42. package/src/pages/search.astro +50 -14
  43. package/src/pages/slides/index.astro +25 -6
  44. package/src/pages/tags/[tag].astro +32 -15
  45. package/src/pages/tags/index.astro +39 -16
  46. package/src/plugins/remark-containers.mjs +351 -322
  47. package/src/plugins/remark-protect-code.mjs +69 -0
  48. package/src/styles/global.css +35 -1
  49. package/templates/default/.claude/ralph-loop.local.md +48 -0
  50. package/templates/default/astro.config.mjs +33 -4
  51. package/templates/default/content/posts/blog_docs_en/01.get-started/01-intro.md +81 -0
  52. package/templates/default/content/posts/blog_docs_en/01.get-started/02-install.md +137 -0
  53. package/templates/default/content/posts/blog_docs_en/01.get-started/03-create-post.md +176 -0
  54. package/templates/default/content/posts/blog_docs_en/01.get-started/04-structure.md +173 -0
  55. package/templates/default/content/posts/blog_docs_en/01.get-started/05-deploy.md +208 -0
  56. package/templates/default/content/posts/blog_docs_en/01.get-started/README.md +52 -0
  57. package/templates/default/content/posts/blog_docs_en/02.guide/02-containers.md +245 -0
  58. package/templates/default/content/posts/blog_docs_en/02.guide/03-code-blocks.md +207 -0
  59. package/templates/default/content/posts/blog_docs_en/02.guide/03-mermaid.md +194 -0
  60. package/templates/default/content/posts/blog_docs_en/02.guide/04-icons.md +229 -0
  61. package/templates/default/content/posts/blog_docs_en/02.guide/06-latex.md +233 -0
  62. package/templates/default/content/posts/blog_docs_en/02.guide/07-video.md +184 -0
  63. package/templates/default/content/posts/blog_docs_en/02.guide/08-slides.md +359 -0
  64. package/templates/default/content/posts/blog_docs_en/02.guide/README.md +213 -0
  65. package/templates/default/content/posts/blog_docs_en/03.config/01-site.md +208 -0
  66. package/templates/default/content/posts/blog_docs_en/03.config/02-sidebar.md +240 -0
  67. package/templates/default/content/posts/blog_docs_en/03.config/03-i18n.md +349 -0
  68. package/templates/default/content/posts/blog_docs_en/03.config/README.md +85 -0
  69. package/templates/default/content/posts/blog_docs_en/README.md +79 -0
  70. package/templates/default/content/posts/blog_docs_zh/01.get-started/01-intro.md +81 -0
  71. package/templates/default/content/posts/blog_docs_zh/01.get-started/02-install.md +137 -0
  72. package/templates/default/content/posts/blog_docs_zh/01.get-started/03-create-post.md +176 -0
  73. package/templates/default/content/posts/blog_docs_zh/01.get-started/04-structure.md +173 -0
  74. package/templates/default/content/posts/blog_docs_zh/01.get-started/05-deploy.md +208 -0
  75. package/templates/default/content/posts/blog_docs_zh/01.get-started/README.md +52 -0
  76. package/templates/default/content/posts/blog_docs_zh/02.guide/02-containers.md +245 -0
  77. package/templates/default/content/posts/blog_docs_zh/02.guide/03-code-blocks.md +206 -0
  78. package/templates/default/content/posts/blog_docs_zh/02.guide/03-mermaid.md +194 -0
  79. package/templates/default/content/posts/blog_docs_zh/02.guide/04-icons.md +229 -0
  80. package/templates/default/content/posts/blog_docs_zh/02.guide/06-latex.md +233 -0
  81. package/templates/default/content/posts/blog_docs_zh/02.guide/07-video.md +184 -0
  82. package/templates/default/content/posts/blog_docs_zh/02.guide/08-slides.md +359 -0
  83. package/templates/default/content/posts/blog_docs_zh/02.guide/README.md +213 -0
  84. package/templates/default/content/posts/blog_docs_zh/03.config/01-site.md +208 -0
  85. package/templates/default/content/posts/blog_docs_zh/03.config/02-sidebar.md +240 -0
  86. package/templates/default/content/posts/blog_docs_zh/03.config/03-i18n.md +348 -0
  87. package/templates/default/content/posts/blog_docs_zh/03.config/README.md +85 -0
  88. package/templates/default/content/posts/blog_docs_zh/README.md +78 -0
  89. package/templates/default/package-lock.json +9667 -0
  90. package/templates/default/package.json +1 -1
  91. package/templates/default/src/config/footer.ts +14 -11
  92. package/templates/default/src/config/locales/en/footer.ts +17 -0
  93. package/templates/default/src/config/locales/en/index.ts +20 -0
  94. package/templates/default/src/config/locales/en/menu.ts +14 -0
  95. package/templates/default/src/config/locales/en/sidebar.ts +34 -0
  96. package/templates/default/src/config/locales/en/site.ts +7 -0
  97. package/templates/default/src/config/locales/en/ui.ts +29 -0
  98. package/templates/default/src/config/locales/index.ts +7 -0
  99. package/templates/default/src/config/locales/zh-CN/footer.ts +17 -0
  100. package/templates/default/src/config/locales/zh-CN/index.ts +20 -0
  101. package/templates/default/src/config/locales/zh-CN/menu.ts +14 -0
  102. package/templates/default/src/config/locales/zh-CN/sidebar.ts +34 -0
  103. package/templates/default/src/config/locales/zh-CN/site.ts +7 -0
  104. package/templates/default/src/config/locales/zh-CN/ui.ts +29 -0
  105. package/templates/default/src/config/sidebar.ts +10 -12
  106. package/templates/default/src/config/site.ts +2 -2
  107. package/templates/default/src/content.config.ts +15 -3
  108. package/templates/default/src/env.d.ts +7 -0
  109. package/dist/chunk-MQXPSOYB.js +0 -124
  110. package/templates/default/content/posts/blog_docs/01-quick-start.md +0 -162
  111. package/templates/default/content/posts/blog_docs/02-frontmatter.md +0 -277
  112. package/templates/default/content/posts/blog_docs/03-markdown-basic.md +0 -350
  113. package/templates/default/content/posts/blog_docs/04-containers.md +0 -331
  114. package/templates/default/content/posts/blog_docs/05-code-blocks.md +0 -388
  115. package/templates/default/content/posts/blog_docs/06-mermaid.md +0 -431
  116. package/templates/default/content/posts/blog_docs/07-video.md +0 -243
  117. package/templates/default/content/posts/blog_docs/08-latex.md +0 -382
  118. package/templates/default/content/posts/blog_docs/09-icons.md +0 -326
  119. package/templates/default/content/posts/blog_docs/10-sidebar.md +0 -445
  120. package/templates/default/content/posts/blog_docs/11-config.md +0 -334
  121. package/templates/default/content/posts/blog_docs/12-slides.mdx +0 -552
  122. package/templates/default/content/posts/blog_docs/README.md +0 -151
@@ -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 };
@@ -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`.
@@ -8,17 +8,38 @@ import rehypeKatex from 'rehype-katex';
8
8
  import rehypeRaw from 'rehype-raw';
9
9
 
10
10
  // Import plugins and integration from @jet-w/astro-blog
11
- import { astroBlog } from '@jet-w/astro-blog';
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';
15
16
  import { rehypeTabs } from '@jet-w/astro-blog/plugins/rehype-tabs.mjs';
16
17
  import { rehypeRelativeLinks } from '@jet-w/astro-blog/plugins/rehype-relative-links.mjs';
17
18
 
19
+ // Import locale-specific configurations
20
+ import { zhCNConfig } from './src/config/locales/zh-CN';
21
+ import { enConfig } from './src/config/locales/en';
22
+
23
+ // i18n configuration - supports any number of languages
24
+ const i18nConfig = defineI18nConfig({
25
+ defaultLocale: 'en',
26
+ locales: [
27
+ { code: 'en', name: 'English', htmlLang: 'en', dateLocale: 'en-US' },
28
+ { code: 'zh-CN', name: '中文', htmlLang: 'zh-CN', dateLocale: 'zh-CN' },
29
+ ],
30
+ routing: {
31
+ prefixDefaultLocale: false, // en (default) uses /posts, zh-CN uses /zh-CN/posts
32
+ },
33
+ localeConfigs: {
34
+ 'en': enConfig,
35
+ 'zh-CN': zhCNConfig,
36
+ },
37
+ });
38
+
18
39
  // https://astro.build/config
19
40
  export default defineConfig({
20
41
  integrations: [
21
- astroBlog(),
42
+ astroBlog({ i18n: i18nConfig }),
22
43
  vue(),
23
44
  mdx(),
24
45
  tailwind({
@@ -27,9 +48,10 @@ export default defineConfig({
27
48
  ],
28
49
  markdown: {
29
50
  remarkPlugins: [
30
- remarkDirective,
51
+ remarkProtectCode, // Must run FIRST to protect code blocks
31
52
  remarkMath,
32
- remarkContainers,
53
+ remarkDirective, // Parse ::: syntax into directive nodes
54
+ remarkContainers, // Handle container syntax (works with both plain text and directive nodes)
33
55
  remarkMermaid,
34
56
  ],
35
57
  rehypePlugins: [
@@ -38,6 +60,7 @@ export default defineConfig({
38
60
  rehypeCleanContainers,
39
61
  rehypeTabs,
40
62
  rehypeRelativeLinks,
63
+ rehypeRestoreCode, // Must run LAST to restore ::: in code blocks
41
64
  ],
42
65
  shikiConfig: {
43
66
  theme: 'github-dark',
@@ -49,5 +72,11 @@ export default defineConfig({
49
72
  base: '/',
50
73
  build: {
51
74
  assets: 'assets'
75
+ },
76
+ vite: {
77
+ resolve: {
78
+ // Help Vite resolve peer dependencies from injected routes
79
+ dedupe: ['@astrojs/rss', 'astro']
80
+ }
52
81
  }
53
82
  });
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: Introduction
3
+ description: What is Astro Blog and why should you use it?
4
+ pubDate: 2025-01-01
5
+ author: jet-w
6
+ categories:
7
+ - Documentation
8
+ tags:
9
+ - Getting Started
10
+ - Introduction
11
+ ---
12
+
13
+ # Introduction
14
+
15
+ Astro Blog is a **modern blog system** built for developers and content creators who want a fast, beautiful, and feature-rich blogging experience.
16
+
17
+ ## What is Astro Blog?
18
+
19
+ Astro Blog is built on top of [Astro](https://astro.build), a modern static site generator. It combines:
20
+
21
+ - **Astro** - For blazing fast static site generation
22
+ - **Vue 3** - For interactive components
23
+ - **Tailwind CSS** - For beautiful, responsive styling
24
+
25
+ ::: tip Static Site Generation
26
+ Your blog is pre-built as static HTML files, meaning:
27
+ - **Instant page loads** - No server processing needed
28
+ - **Better SEO** - Search engines love static content
29
+ - **Easy hosting** - Deploy anywhere (Vercel, Netlify, GitHub Pages)
30
+ :::
31
+
32
+ ## Key Features
33
+
34
+ ### Writing Features
35
+
36
+ | Feature | Description |
37
+ |---------|-------------|
38
+ | Markdown/MDX | Write in Markdown with component support |
39
+ | Code Highlighting | Beautiful syntax highlighting for 100+ languages |
40
+ | Math Formulas | LaTeX math with KaTeX |
41
+ | Diagrams | Flowcharts and diagrams with Mermaid |
42
+ | Containers | Callouts, tips, warnings, and more |
43
+ | Videos | Embed YouTube, Bilibili, or self-hosted videos |
44
+
45
+ ### System Features
46
+
47
+ | Feature | Description |
48
+ |---------|-------------|
49
+ | Dark Mode | Toggle between light and dark themes |
50
+ | Responsive | Perfect on desktop, tablet, and mobile |
51
+ | Search | Full-text search across all posts |
52
+ | RSS Feed | Auto-generated RSS for subscribers |
53
+ | SEO | Optimized meta tags and sitemap |
54
+ | i18n | Multi-language support |
55
+
56
+ ## When to Use Astro Blog?
57
+
58
+ Astro Blog is perfect for:
59
+
60
+ ::: info Good Use Cases
61
+ - **Tech blogs** - Share tutorials and technical knowledge
62
+ - **Personal blogs** - Document your journey and thoughts
63
+ - **Documentation** - Create product or project docs
64
+ - **Portfolios** - Showcase your work with blog posts
65
+ :::
66
+
67
+ ## Tech Stack
68
+
69
+ ::: details View Full Stack
70
+ - **Framework**: [Astro](https://astro.build) v5.x
71
+ - **UI Components**: [Vue 3](https://vuejs.org)
72
+ - **Styling**: [Tailwind CSS](https://tailwindcss.com) v4.x
73
+ - **Code Highlighting**: [Shiki](https://shiki.style)
74
+ - **Math**: [KaTeX](https://katex.org)
75
+ - **Diagrams**: [Mermaid](https://mermaid.js.org)
76
+ - **Icons**: Font Awesome, Material Icons, Remix Icon, Bootstrap Icons
77
+ :::
78
+
79
+ ---
80
+
81
+ Ready to set up your blog? Continue to [Installation](./02-install).
@@ -0,0 +1,137 @@
1
+ ---
2
+ title: Installation
3
+ description: Set up your development environment and install Astro Blog
4
+ pubDate: 2025-01-01
5
+ author: jet-w
6
+ categories:
7
+ - Documentation
8
+ tags:
9
+ - Getting Started
10
+ - Installation
11
+ ---
12
+
13
+ # Installation
14
+
15
+ This guide will help you set up Astro Blog on your computer.
16
+
17
+ ## Prerequisites
18
+
19
+ Before you begin, ensure you have:
20
+
21
+ ### Node.js
22
+
23
+ Node.js 18.x or higher is required.
24
+
25
+ ```bash
26
+ # Check your Node.js version
27
+ node --version
28
+ # Should output: v18.x.x or higher
29
+ ```
30
+
31
+ ::: tip Installing Node.js
32
+ If you don't have Node.js, download it from [nodejs.org](https://nodejs.org).
33
+ Choose the **LTS** version for the best stability.
34
+ :::
35
+
36
+ ### Package Manager
37
+
38
+ npm comes with Node.js. You can also use pnpm or yarn:
39
+
40
+ ```bash
41
+ # Check npm version
42
+ npm --version
43
+
44
+ # Or use pnpm (recommended for faster installs)
45
+ npm install -g pnpm
46
+ pnpm --version
47
+ ```
48
+
49
+ ## Install Dependencies
50
+
51
+ Navigate to your blog project folder and install dependencies:
52
+
53
+ ```bash
54
+ # Using npm
55
+ npm install
56
+
57
+ # Or using pnpm
58
+ pnpm install
59
+ ```
60
+
61
+ This will install all required packages defined in `package.json`.
62
+
63
+ ## Start Development Server
64
+
65
+ Start the local development server:
66
+
67
+ ```bash
68
+ # Using npm
69
+ npm run dev
70
+
71
+ # Or using pnpm
72
+ pnpm dev
73
+ ```
74
+
75
+ You should see output like:
76
+
77
+ ```
78
+ 🚀 astro v5.x.x ready in 1234ms
79
+
80
+ ┃ Local http://localhost:4321/
81
+ ┃ Network use --host to expose
82
+ ```
83
+
84
+ ::: tip Hot Reload
85
+ The development server supports hot reload. When you save a file, the browser automatically refreshes to show your changes.
86
+ :::
87
+
88
+ ## Open in Browser
89
+
90
+ Visit `http://localhost:4321` in your browser. You should see your blog's homepage!
91
+
92
+ ## Verify Installation
93
+
94
+ Check that everything works:
95
+
96
+ 1. **Homepage loads** - You see the blog homepage
97
+ 2. **Posts list** - Navigate to `/posts` to see articles
98
+ 3. **Dark mode** - Toggle the theme switch in the header
99
+ 4. **Search** - Try the search function
100
+
101
+ ## Common Issues
102
+
103
+ ### Port Already in Use
104
+
105
+ If port 4321 is busy, Astro will use another port. Check the terminal output for the actual URL.
106
+
107
+ Or specify a different port:
108
+
109
+ ```bash
110
+ npm run dev -- --port 3000
111
+ ```
112
+
113
+ ### Dependencies Not Installing
114
+
115
+ Try clearing the cache:
116
+
117
+ ```bash
118
+ # Remove node_modules and lock file
119
+ rm -rf node_modules package-lock.json
120
+
121
+ # Reinstall
122
+ npm install
123
+ ```
124
+
125
+ ### Node.js Version Too Old
126
+
127
+ Update Node.js to version 18 or higher. Consider using [nvm](https://github.com/nvm-sh/nvm) to manage Node versions:
128
+
129
+ ```bash
130
+ # Install nvm, then:
131
+ nvm install 20
132
+ nvm use 20
133
+ ```
134
+
135
+ ---
136
+
137
+ Development server running? Great! Let's [create your first post](./03-create-post).
@@ -0,0 +1,176 @@
1
+ ---
2
+ title: Create Your First Post
3
+ description: Write and publish your first blog article
4
+ pubDate: 2025-01-01
5
+ author: jet-w
6
+ categories:
7
+ - Documentation
8
+ tags:
9
+ - Getting Started
10
+ - Writing
11
+ ---
12
+
13
+ # Create Your First Post
14
+
15
+ Let's write your first blog post! This is where the fun begins.
16
+
17
+ ## Where Posts Live
18
+
19
+ All blog posts go in the `content/posts/` directory:
20
+
21
+ ```
22
+ content/
23
+ └── posts/
24
+ ├── my-first-post.md ← Your posts go here
25
+ ├── another-post.md
26
+ └── tech/ ← Or in subdirectories
27
+ └── tutorial.md
28
+ ```
29
+
30
+ ## Create a New Post
31
+
32
+ Create a file called `hello-world.md` in `content/posts/`:
33
+
34
+ ```markdown
35
+ ---
36
+ title: Hello World
37
+ description: My first blog post
38
+ pubDate: 2025-01-15
39
+ author: Your Name
40
+ tags:
41
+ - Introduction
42
+ categories:
43
+ - Personal
44
+ ---
45
+
46
+ # Hello World
47
+
48
+ Welcome to my blog! This is my first post.
49
+
50
+ ## Why I Started Blogging
51
+
52
+ I started this blog to:
53
+
54
+ 1. Share what I learn
55
+ 2. Document my journey
56
+ 3. Connect with others
57
+
58
+ > The best time to start was yesterday. The second best time is now.
59
+
60
+ ## What's Next
61
+
62
+ Stay tuned for more posts about:
63
+
64
+ - Web development
65
+ - My projects
66
+ - Lessons learned
67
+
68
+ Thanks for reading!
69
+ ```
70
+
71
+ ## View Your Post
72
+
73
+ Save the file and visit:
74
+
75
+ ```
76
+ http://localhost:4321/posts/hello-world
77
+ ```
78
+
79
+ Your post should appear with full styling!
80
+
81
+ ## Understanding Frontmatter
82
+
83
+ The section between `---` markers is called **frontmatter**. It contains metadata about your post:
84
+
85
+ ```yaml
86
+ ---
87
+ title: Hello World # Required - Post title
88
+ description: My first post # For SEO and previews
89
+ pubDate: 2025-01-15 # Publication date
90
+ author: Your Name # Author name
91
+ tags: # Tags (array)
92
+ - Introduction
93
+ categories: # Categories (array)
94
+ - Personal
95
+ draft: false # true = hidden from listing
96
+ star: false # true = featured post
97
+ ---
98
+ ```
99
+
100
+ ::: tip Required vs Optional
101
+ Only `title` is required. All other fields are optional but recommended for better organization and SEO.
102
+ :::
103
+
104
+ ## Using Subdirectories
105
+
106
+ Organize related posts in subdirectories:
107
+
108
+ ```
109
+ content/posts/
110
+ ├── tutorials/
111
+ │ ├── README.md ← Shows at /posts/tutorials
112
+ │ ├── javascript.md ← Shows at /posts/tutorials/javascript
113
+ │ └── css.md ← Shows at /posts/tutorials/css
114
+ └── projects/
115
+ └── my-app.md ← Shows at /posts/projects/my-app
116
+ ```
117
+
118
+ ### Directory README
119
+
120
+ Each directory can have a `README.md` that serves as the directory's index page:
121
+
122
+ ```markdown
123
+ ---
124
+ title: Tutorials
125
+ description: Learn web development step by step
126
+ ---
127
+
128
+ # Tutorials
129
+
130
+ Welcome to my tutorials section!
131
+
132
+ - [JavaScript Basics](./javascript)
133
+ - [CSS Tricks](./css)
134
+ ```
135
+
136
+ ## URL Path Rules
137
+
138
+ Your file path determines the URL:
139
+
140
+ | File Path | URL |
141
+ |-----------|-----|
142
+ | `posts/hello.md` | `/posts/hello` |
143
+ | `posts/tech/intro.md` | `/posts/tech/intro` |
144
+ | `posts/tech/README.md` | `/posts/tech` |
145
+
146
+ ::: info Case Insensitive
147
+ URLs are automatically lowercased. `Hello-World.md` becomes `/posts/hello-world`.
148
+ :::
149
+
150
+ ## Adding Images
151
+
152
+ Place images in `public/images/` and reference them:
153
+
154
+ ```markdown
155
+ ![My Photo](/images/photo.jpg)
156
+ ```
157
+
158
+ For post-specific images, you can create a folder:
159
+
160
+ ```
161
+ public/
162
+ └── images/
163
+ └── posts/
164
+ └── hello-world/
165
+ └── cover.jpg
166
+ ```
167
+
168
+ Then use:
169
+
170
+ ```markdown
171
+ ![Cover](/images/posts/hello-world/cover.jpg)
172
+ ```
173
+
174
+ ---
175
+
176
+ Congratulations on your first post! Next, let's understand the [project structure](./04-structure).