fix(landing): stabilize blog indexing workflows (#2042)

Use full workspace installs for blog indexing workflows so root postinstall can resolve workspace build dependencies, and enrich sitemap metadata for blog URLs from frontmatter dates.

Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ashleyashli 2026-05-18 15:52:29 +08:00 committed by GitHub
parent d55f05fcfa
commit 0163fa9d84
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 51 additions and 5 deletions

View file

@ -59,8 +59,8 @@ jobs:
node-version: 24
cache: pnpm
- name: Install dependencies (landing-page only)
run: pnpm install --frozen-lockfile --filter @open-design/landing-page
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check indexing configuration
id: config

View file

@ -72,8 +72,8 @@ jobs:
node-version: 24
cache: pnpm
- name: Install dependencies (landing-page only)
run: pnpm install --frozen-lockfile --filter @open-design/landing-page
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check indexing configuration
id: config

View file

@ -1,4 +1,6 @@
import sitemap from '@astrojs/sitemap';
import sitemap, { type SitemapItem } from '@astrojs/sitemap';
import { readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { defineConfig } from 'astro/config';
// Production canonical origin. Used by Astro for `Astro.site`, by
@ -10,6 +12,24 @@ import { defineConfig } from 'astro/config';
// builds (Cloudflare Pages preview deployments, local previews on a
// different host) can stamp their own URL without forking the config.
const site = process.env.OD_LANDING_SITE ?? 'https://open-design.ai';
const changefreq = {
daily: 'daily' as SitemapItem['changefreq'],
weekly: 'weekly' as SitemapItem['changefreq'],
monthly: 'monthly' as SitemapItem['changefreq'],
};
// Read blog post dates at config time so the sitemap can include lastmod.
const blogDir = join(import.meta.dirname, 'app/content/blog');
const blogDates = new Map<string, string>();
for (const file of readdirSync(blogDir)) {
if (!file.endsWith('.md') || file.startsWith('_')) continue;
const raw = readFileSync(join(blogDir, file), 'utf-8');
const match = raw.match(/^date:\s*(\d{4}-\d{2}-\d{2})/m);
if (match) {
const slug = file.replace(/\.md$/, '');
blogDates.set(`/blog/${slug}/`, match[1]!);
}
}
export default defineConfig({
output: 'static',
@ -24,6 +44,32 @@ export default defineConfig({
// and is `Disallow`-ed from `public/robots.txt`. Filtering it
// out of the sitemap keeps the index strictly canonical pages.
filter: (page) => !page.includes('/og/'),
serialize(item: SitemapItem) {
const path = new URL(item.url).pathname;
if (path === '/') {
item.priority = 1.0;
item.changefreq = changefreq.daily;
} else if (path === '/blog/') {
item.priority = 0.9;
item.changefreq = changefreq.daily;
} else if (path.startsWith('/blog/')) {
item.priority = 0.8;
item.changefreq = changefreq.weekly;
const date = blogDates.get(path);
if (date) item.lastmod = date;
} else if (
path === '/skills/' ||
path === '/systems/' ||
path === '/craft/'
) {
item.priority = 0.7;
item.changefreq = changefreq.weekly;
} else {
item.priority = 0.5;
item.changefreq = changefreq.monthly;
}
return item;
},
}),
],
});