Blog with Astro
TODO
- Dynamic routing
- Global style.css & related files
- favicon
-
MDX + svelte- Alpine.js
- UnoCSS
- OGP preview image
- RSS
- [v] Sitemap
- robots.txt
Markdown + 彈性路由
1. .glob
- Using dynamic routes to organize blog posts in Astro - SeanMcP.com
- 文內的
.fetchContent
已經棄用,需改為.glob
[slug].astro
:
--- export async function getStaticPaths() { const content = await Astro.glob('./posts/*.{md,mdx}') return content.map((item) => ({ params: { slug: item.url.split("/").pop() }, props: { ...item, }, })); } const { Content, frontmatter: { title }, } = Astro.props; --- <h1>{title}</h1> <Content />
- 文內的
2. Collections
- Content Collections 🚀 Astro 文檔
- How to use content collection in Astro. - DEV Community
- AstroでMDファイルの管理にContent Collectionsを利用する - to-R Media
- Astro 系列文第十六日:內容集合 - 網頁東東
- 定義集合:
content/config.ts
import { z, defineCollection } from 'astro:content'; const blogCollection = defineCollection({ schema: z.object({ title: z.string(), date: z.date(), summary: z.string(), tags: z.array(z.string()), }) }); // 輸出名稱需與文件資料夾相同 export const collections = { 'blog': blogCollection, };
script/blog.ts
import { getCollection } from 'astro:content'; export async function getAllBlogs() { const blogs = await getCollection('blog'); return blogs .map(blog => ({ params: { slug: blog.slug }, props: { blog },})) .sort( (a, z) => new Date(z.props.blog.data.date).getMilliseconds() - new Date(a.props.blog.data.date).getMilliseconds() ) }
[slug].astro
--- import { getAllBlogs } from "../scripts/blog"; import MarkdownPostLayout from "../layouts/MarkdownPostLayout.astro"; export async function getStaticPaths() { const content = await getAllBlogs(); return content; } const { blog } = Astro.props; const { Content } = await blog.render(); --- <MarkdownPostLayout title={blog.data.title}> <Content /> </MarkdownPostLayout>
MDX
- Markdown + JSX
- @astrojs/mdx 🚀 Astro 文檔
- 安裝
npx astro add mdx
RSS feed
- Add an RSS feed 🚀 Astro 文檔
npm install @astrojs/rss
- 設定
- 需先於
astro.config
裡設定site
pages/rss.xml.js
import rss from '@astrojs/rss'; import { getCollection } from 'astro:content'; export async function GET(context) { const blog = await getCollection('blog'); return rss({ title: "title", description: "description", site: context.site, items: blog.map((post) => ({ title: post.data.title, pubDate: post.data.date, description: post.data.description, link: `/${post.slug}`, })), }) }
- 需先於
Sitemap
- @astrojs/sitemap 🚀 Astro 文檔
npx astro add sitemap
- 設定
layouts/Layout.astro
<head> <link rel="sitemap" href="/sitemap.xml" /> </head>
astro.config.mjs
robots.txt
- astro-lib/packages/astro-robots-txt
npx astro add astro-robots-txt
OGP preview
astro-og-canvas
satori
- Astro.js 小ネタ集 その②
npm i satori satori-html @resvg/resvg-js
- Error:
No loader is configured for ".node" files: node_modules/@resvg/resvg-js-linux-x64-musl/resvgjs.linux-x64-musl.node
astro.config.mjs
vite: { ssr: { external: ['@resvg/resvg-js'] }, optimizeDeps: { exclude: ["@resvg/resvg-js"] } }
- Satori 使用與 React Native 同樣的 layout 引擎,沒有實作完整的 CSS
- 支援 TailwindCSS
- https://og-playground.vercel.app/
Puppeteer
SEO
favicon
Alpine.js
- @astrojs/alpinejs 🚀 Astro 文檔
npx astro add alpinejs
UnoCSS
- UnoCSS Astro Integration
npm i -D unocss
astro.config.mjs
import { defineConfig } from 'astro/config' import UnoCSS from 'unocss/astro' export default defineConfig({ integrations: [ UnoCSS(), ], })
- 建立
uno.config.ts
import { defineConfig, presetUno, presetAttributify, } from 'unocss' export default defineConfig({ presets: [ presetUno(), presetAttributify(), ], })
- 加入 Presets:Uno 與 Attributify
- Attributify 預設屬性值:
['bg', 'flex', 'grid', 'border', 'text', 'font', 'class', 'className', 'p', 'm', 'animate']
UnoCSS classes also work in Markdown!
Pagefind
Pass variable from frontmatter to script
- javascript - how to pass variable from frontmatter to script in Astro JS? - Stack Overflow
- Scripts and Event Handling 🚀 Astro 文檔
swup
- swup/astro: Astro integration for swup 🚀
- [Integrations — swup https://swup.js.org/other/integrations/]
npm i @swup/astro