--- import { readFileSync } from 'fs'; import { join } from 'path'; import AppLayout from '../layouts/AppLayout.astro'; import { marked } from 'marked'; const user = Astro.locals.user; // Single-file roadmap — not a content collection const raw = readFileSync(join(process.cwd(), 'content/roadmap.md'), 'utf-8'); // Strip YAML frontmatter const body = raw.replace(/^---[\s\S]*?---\n/, ''); // Parse sections by ## headings function parseSections(md: string) { const sectionRe = /^## (.+)$/gm; const sections: { title: string; items: { title: string; body: string; pilotOnly: boolean }[] }[] = []; const matches = [...md.matchAll(sectionRe)]; for (let i = 0; i < matches.length; i++) { const m = matches[i]; const start = m.index! + m[0].length; const end = matches[i + 1]?.index ?? md.length; const sectionBody = md.slice(start, end).trim(); // Each item starts with **Title** — description const itemRe = /\*\*([^*]+)\*\*\s*—\s*([\s\S]*?)(?=\n\n\*\*|\n\n##|$)/g; const items: { title: string; body: string; pilotOnly: boolean }[] = []; let itemMatch: RegExpExecArray | null; while ((itemMatch = itemRe.exec(sectionBody)) !== null) { const rawBody = itemMatch[2].trim(); const pilotOnly = rawBody.includes('`pilot-only`'); const cleanBody = rawBody.replace(/`pilot-only`/g, '').trim(); items.push({ title: itemMatch[1], body: cleanBody, pilotOnly }); } sections.push({ title: m[1], items }); } return sections; } const sections = parseSections(body); const horizonColors: Record = { 'In progress': 'var(--pigment-copper)', 'Next': 'var(--pigment-ochre)', 'Later': 'var(--pigment-indigo)', }; ---
{sections.map((section) => (
    {section.items.map((item) => (
  • {item.title}

    {item.pilotOnly && ( Pilot )}

    {item.body}

  • ))}
))}