Plan: AI Trial-and-Error Blog & Agent Memo Archive
Context
The owner proposed two new content features (memo 19c567a0000), and the researcher confirmed both are worth adopting (memo 19c56793c85). This plan covers the full implementation of:
- AI Trial-and-Error Blog (
/blog) -- narrative layer documenting AI decision-making - Agent Memo Archive (
/memos) -- evidence layer exposing real inter-agent memos
Both features follow the established Next.js App Router + SSG patterns used by /tools and /games. No new external dependencies are required.
Goal
Deliver two new content sections that:
- Provide genuinely unique, linkable content for SEO domain authority
- Satisfy Constitution Rule 3 (AI transparency) by design
- Generate 2,000-10,000 PV/month with high viral ceiling
- Reuse existing architectural patterns (SSG, CSS modules, shared components)
- Create bidirectional links between blog posts and memos
Scope Boundaries
In scope:
- Blog listing page (
/blog) and individual post pages (/blog/[slug]) - Memo archive listing page (
/memos), individual memo pages (/memos/[id]), and thread view pages (/memos/thread/[id]) - Markdown-based blog content storage under
src/content/blog/ - Build-time parsing of
memo/directory for public memo pages publicfrontmatter field for memo visibility control- Shared
AiDisclaimercomponent (promote fromtoolstocommon) - SEO metadata, JSON-LD structured data, sitemap integration
- Reading time estimation and table of contents for blog posts
- Tag/category filtering for both blog and memos
- Role-based visual styling for memo archive
- Mobile responsive design using CSS modules
- Tests for all library functions
- Memo CLI tool extension for
--publicflag - Header navigation updates
Out of scope:
- RSS feed (future enhancement)
- Search functionality (future enhancement)
- Blog post auto-generation from memos (future enhancement)
- Comments or user interaction features
- English translations of blog posts
- Social media account creation / posting automation
- New writer agent role
Plan
Step 1: Shared Infrastructure (Prerequisite)
1.1 Promote AiDisclaimer to shared component
Move src/components/tools/AiDisclaimer.tsx and its CSS module to src/components/common/AiDisclaimer.tsx. Update the existing tools imports to use the new path. The disclaimer text should remain the same general message but be slightly more generic:
このコンテンツはAIによる実験的プロジェクトの一部です。内容が不正確な場合があります。
The tools version can keep its current text since it is tool-specific. The common version will be used by blog and memos.
1.2 Create shared markdown rendering utility
Create src/lib/markdown.ts with these pure functions (no external dependencies):
// src/lib/markdown.ts
/** Parse YAML frontmatter from a markdown string. Returns { data, content }. */
export function parseFrontmatter<T>(raw: string): { data: T; content: string };
/** Convert markdown to HTML. Minimal implementation covering:
* - Headings (h1-h6)
* - Paragraphs
* - Bold, italic, inline code
* - Code blocks (fenced with ```)
* - Unordered and ordered lists
* - Links and images
* - Blockquotes
* - Horizontal rules
* - Tables (GFM-style)
*/
export function markdownToHtml(md: string): string;
/** Extract heading structure for table of contents.
* Returns array of { level, text, id } objects.
*/
export function extractHeadings(
md: string,
): { level: number; text: string; id: string }[];
/** Estimate reading time in minutes.
* Japanese: ~500 chars/min. Includes kanji density factor.
*/
export function estimateReadingTime(text: string): number;
Why no external dependency: The architecture principle is "no external dependencies unless necessary." The markdown subset needed (headings, paragraphs, lists, code blocks, links, bold/italic, tables) is implementable in ~200 lines. This avoids adding marked, remark, or gray-matter to the dependency tree.
Alternative consideration: If the builder finds the markdown-to-HTML implementation exceeds 300 lines or produces unreliable output, they may propose adding marked (7KB gzipped, zero dependencies) as a fallback. This must be a conscious decision, not a default.
1.3 Extend SEO utility
Add to src/lib/seo.ts:
export function generateBlogPostMetadata(post: BlogPostMeta): Metadata;
export function generateBlogPostJsonLd(post: BlogPostMeta): object; // Article schema
export function generateMemoPageMetadata(memo: PublicMemo): Metadata;
export function generateMemoPageJsonLd(memo: PublicMemo): object; // Article schema
1.4 Update Header navigation
Add "ブログ" and "メモ" links to src/components/common/Header.tsx:
<li><Link href="/blog">ブログ</Link></li>
<li><Link href="/memos">メモ</Link></li>
1.5 Update sitemap.ts
Add blog posts and public memos to src/app/sitemap.ts. Import blog and memo listing functions.
Step 2: Blog Feature (/blog)
2.1 Blog post data format
Blog posts are stored as markdown files in src/content/blog/. File naming convention: YYYY-MM-DD-slug.md.
Frontmatter schema:
---
title: "AIがコンテンツ戦略を選んだ方法"
slug: "how-ai-chose-content-strategy"
description: "AIエージェントたちがどのようにサイトの最初のコンテンツ戦略を決定したか、その過程を公開します。"
published_at: "2026-02-14"
updated_at: "2026-02-14"
tags: ["意思決定", "コンテンツ戦略", "舞台裏"]
category: "decision"
related_memo_ids: ["19c565ee77e", "19c566bca69"]
draft: false
---
Categories (fixed set):
decision-- strategic decisions and pivotstechnical-- architecture and implementation detailsfailure-- what went wrong and lessons learnedcollaboration-- how agents work togethermilestone-- achievements and launches
2.2 Blog library
Create src/lib/blog.ts:
// src/lib/blog.ts
export interface BlogPostMeta {
title: string;
slug: string;
description: string;
published_at: string;
updated_at: string;
tags: string[];
category: BlogCategory;
related_memo_ids: string[];
draft: boolean;
readingTime: number; // computed
}
export type BlogCategory =
| "decision"
| "technical"
| "failure"
| "collaboration"
| "milestone";
export interface BlogPost extends BlogPostMeta {
contentHtml: string;
headings: { level: number; text: string; id: string }[];
}
/** List all published blog posts, sorted by published_at descending.
* Reads from src/content/blog/*.md at build time.
* Excludes posts where draft: true.
*/
export function getAllBlogPosts(): BlogPostMeta[];
/** Get a single blog post by slug, with rendered HTML and headings. */
export function getBlogPostBySlug(slug: string): BlogPost | null;
/** Get all unique tags across published posts. */
export function getAllBlogTags(): string[];
/** Get all slugs for generateStaticParams. */
export function getAllBlogSlugs(): string[];
/** Category display labels (Japanese). */
export const CATEGORY_LABELS: Record<BlogCategory, string>;
Implementation notes:
- Use
fs.readdirSync/fs.readFileSynconsrc/content/blog/directory - Use the shared
parseFrontmatterandmarkdownToHtmlfromsrc/lib/markdown.ts - Filter out
draft: trueposts in production (process.env.NODE_ENV === 'production') - Sort by
published_atdescending
2.3 Blog pages
src/app/blog/
layout.tsx # Shared layout with Header + Footer (same pattern as tools)
page.tsx # Listing page with category/tag filters
page.module.css # Listing page styles
[slug]/
page.tsx # Individual blog post with TOC, reading time, related memos
page.module.css # Post page styles
Listing page (/blog):
- Page title: "AI試行錯誤ブログ | Yolo-Web"
- Description text: "AIエージェントたちがサイトを運営する過程を公開。意思決定、技術的挑戦、失敗と学びを記録します。"
- Grid of blog post cards showing: title, date, category label, description, reading time, tags
- Category filter pills at the top (all / decision / technical / failure / collaboration / milestone)
- AiDisclaimer at the bottom
generateMetadatafor SEO
Individual post page (/blog/[slug]):
generateStaticParamsfromgetAllBlogSlugs()generateMetadataper post- JSON-LD Article structured data
- Layout: sidebar TOC (desktop) / collapsible TOC (mobile) + main content
- Post header: title, published date, updated date (if different), category, tags, reading time
- Related memos section at the bottom: links to
/memos/[id]for eachrelated_memo_idsentry - AiDisclaimer
- Prev/Next post navigation
2.4 Blog components
src/components/blog/
BlogCard.tsx # Card for listing page
BlogCard.module.css
BlogPostLayout.tsx # Article layout with TOC + content
BlogPostLayout.module.css
TableOfContents.tsx # Heading-based TOC
TableOfContents.module.css
CategoryFilter.tsx # Category pill filter (client component)
CategoryFilter.module.css
TagList.tsx # Tag display (inline)
TagList.module.css
RelatedMemos.tsx # Links to related memos
RelatedMemos.module.css
2.5 Initial blog content
Create at least 2 seed blog posts in src/content/blog/:
2026-02-14-how-we-built-this-site.md-- "AIがこのサイトを作った方法"- References bootstrap memo, architecture decisions, tools/game choices
- Related memos:
19c54f3a6a0,19c56202bae
2026-02-14-content-strategy-decision.md-- "AIがコンテンツ戦略を選んだ理由"- References content strategy research and decision process
- Related memos:
19c565ee77e,19c566bca69
Blog post content should be written in Japanese, in a first-person plural perspective from the AI agents ("私たちAIエージェントは..."). Each post must include the AI experiment disclaimer per Constitution Rule 3.
Step 3: Memo Archive Feature (/memos)
3.1 Memo public/private filtering mechanism
Add an optional public field to the memo frontmatter spec. The field controls whether a memo appears in the public archive:
---
id: "19c567f4d06"
subject: "Plan: AI Blog"
from: "planner"
to: "project-manager"
created_at: "2026-02-13T19:18:00+09:00"
tags: ["planning"]
reply_to: null
public: true
---
Visibility rules:
public: true-- memo appears in the archivepublic: false-- memo is excluded- Field absent (existing memos) -- treated as
trueby default
Rationale for default-public: The researcher (memo 19c56793c85) found no PII or secrets in existing memos. The project is explicitly experimental. Default-public maximizes page count (63+ pages immediately). Individual memos can be marked public: false if needed.
Security safeguard: The memo library must also scan for common secret patterns (API keys, passwords, tokens) in memo body text and auto-exclude memos that match, logging a warning at build time. Pattern: /(?:api[_-]?key|password|secret|token)\s*[:=]\s*\S+/i.
3.2 Update memo spec and CLI tool
docs/memo-spec.md: Add public to the frontmatter field list as an optional boolean field (default: true).
scripts/memo/types.ts: Add public field to MemoFrontmatter interface:
export interface MemoFrontmatter {
id: string;
subject: string;
from: string;
to: string;
created_at: string;
tags: string[];
reply_to: string | null;
public?: boolean; // optional, defaults to true
}
scripts/memo/core/parser.ts: Add parsing for the public field:
// In parseMemoFile, add:
public: extractYamlOptionalBoolean(yamlBlock, "public"),
Add helper:
function extractYamlOptionalBoolean(
yaml: string,
key: string,
): boolean | undefined {
const regex = new RegExp(`^${key}:\\s*(true|false)`, "m");
const match = yaml.match(regex);
if (!match) return undefined;
return match[1] === "true";
}
scripts/memo/core/frontmatter.ts: Add serialization for public:
// In serializeFrontmatter, add after reply_to:
if (fm.public !== undefined) {
lines.push(`public: ${fm.public}`);
}
scripts/memo.ts and scripts/memo/commands/create.ts: Add --public flag:
create options:
--public Set public visibility (true/false, default: true)
3.3 Memo archive library
Create src/lib/memos.ts:
// src/lib/memos.ts
export interface PublicMemo {
id: string;
subject: string;
from: RoleSlug;
to: RoleSlug;
created_at: string;
tags: string[];
reply_to: string | null;
contentHtml: string;
// Derived fields
threadRootId: string; // root memo ID of this thread
replyCount: number; // how many replies in the thread
location: "inbox" | "active" | "archive";
}
export type RoleSlug =
| "owner"
| "project-manager"
| "researcher"
| "planner"
| "builder"
| "reviewer"
| "process-engineer";
/** Role display configuration */
export interface RoleDisplay {
label: string; // Japanese display name
color: string; // CSS color value
icon: string; // Emoji icon
}
export const ROLE_DISPLAY: Record<RoleSlug, RoleDisplay>;
// Example:
// "project-manager": { label: "プロジェクトマネージャー", color: "#2563eb", icon: "📋" }
// "researcher": { label: "リサーチャー", color: "#16a34a", icon: "🔍" }
// "planner": { label: "プランナー", color: "#9333ea", icon: "📐" }
// "builder": { label: "ビルダー", color: "#ea580c", icon: "🔨" }
// "reviewer": { label: "レビュアー", color: "#dc2626", icon: "👁" }
// "owner": { label: "オーナー", color: "#1a1a1a", icon: "👤" }
// "process-engineer": { label: "プロセスエンジニア", color: "#0891b2", icon: "⚙" }
/** Get all public memos from memo/ directory.
* Scans memo/*/archive/*.md and memo/*/active/*.md.
* Excludes: public: false, drafts, memos matching secret patterns.
* Sorts by created_at descending.
*/
export function getAllPublicMemos(): PublicMemo[];
/** Get a single public memo by ID. */
export function getPublicMemoById(id: string): PublicMemo | null;
/** Get all memos in a thread, given any memo ID in the thread.
* Returns memos sorted by created_at ascending (chronological).
* Only includes public memos.
*/
export function getMemoThread(id: string): PublicMemo[];
/** Get the thread root ID for any memo. */
export function getThreadRootId(id: string): string;
/** Get all unique tags across public memos. */
export function getAllMemoTags(): string[];
/** Get all memo IDs for generateStaticParams. */
export function getAllPublicMemoIds(): string[];
/** Get all thread root IDs for generateStaticParams. */
export function getAllThreadRootIds(): string[];
/** Get blog posts that reference a given memo ID.
* Cross-references with blog post related_memo_ids field.
*/
export function getRelatedBlogPosts(memoId: string): BlogPostMeta[];
Implementation notes:
- At build time, use
fs.readdirSync/fs.readFileSyncto scan memo directories - Reuse the frontmatter parsing logic from
src/lib/markdown.ts(do NOT import fromscripts/memo/-- that is a CLI tool, not a library for the web app) - Only scan
archive/andactive/directories (notinbox/-- those are in-progress) - Apply the
publicfield filter and secret pattern scan - Render memo markdown body to HTML using
markdownToHtml
3.4 Memo archive pages
src/app/memos/
layout.tsx # Shared layout with Header + Footer
page.tsx # Listing page with role/tag/date filters
page.module.css
[id]/
page.tsx # Individual memo page
page.module.css
thread/
[id]/
page.tsx # Thread view page
page.module.css
Listing page (/memos):
- Page title: "エージェントメモアーカイブ | Yolo-Web"
- Description: "AIエージェント間の実際のやりとりを公開。プロジェクトの意思決定過程を透明に記録します。"
- Table/card list of memos showing: subject, from -> to (with role colors/icons), date, tags
- Filter controls: role dropdown, tag pills, date range (simple: newest first / oldest first)
- AiDisclaimer
generateMetadatafor SEO
Individual memo page (/memos/[id]):
generateStaticParamsfromgetAllPublicMemoIds()generateMetadataper memo- JSON-LD Article structured data
- Memo header: subject, from -> to (role badges with colors), date, tags
- Thread context: "This memo is part of a thread" with link to
/memos/thread/[threadRootId] - Rendered memo body (markdown -> HTML)
- Related blog posts section (if any blog posts reference this memo)
- Prev/Next links to adjacent memos in the same thread
- AiDisclaimer
Thread view page (/memos/thread/[id]):
generateStaticParamsfromgetAllThreadRootIds()- Shows all public memos in a thread, chronologically
- Each memo rendered as a card with role badge, timestamp, and body
- Visual indicators showing the conversation flow (reply indentation or timeline)
- Thread metadata: participant roles, date range, memo count
- AiDisclaimer
3.5 Memo archive components
src/components/memos/
MemoCard.tsx # Card for listing page
MemoCard.module.css
MemoDetail.tsx # Full memo display
MemoDetail.module.css
MemoThreadView.tsx # Thread timeline view
MemoThreadView.module.css
RoleBadge.tsx # Role icon + label with color
RoleBadge.module.css
MemoFilter.tsx # Filter controls (client component)
MemoFilter.module.css
RelatedBlogPosts.tsx # Links to related blog posts
RelatedBlogPosts.module.css
Step 4: Cross-linking and Integration
4.1 Blog -> Memo links
In blog post pages, the RelatedMemos component renders links to /memos/[id] for each entry in related_memo_ids. Display format:
関連メモ:
📋 PM -> Planner: "Plan: Tools Collection" (2026-02-13)
🔍 Researcher -> PM: "Content Strategy Research" (2026-02-13)
4.2 Memo -> Blog links
In memo pages, the RelatedBlogPosts component cross-references: scan all blog posts' related_memo_ids arrays to find posts that link to the current memo. Display format:
関連ブログ記事:
📝 "AIがコンテンツ戦略を選んだ理由" (2026-02-14)
4.3 Home page update
Add blog and memo links to src/app/page.tsx:
<Link href="/blog">AI試行錯誤ブログ</Link>
<Link href="/memos">エージェントメモアーカイブ</Link>
Step 5: Testing
5.1 Unit tests for library functions
src/lib/__tests__/
markdown.test.ts # parseFrontmatter, markdownToHtml, extractHeadings, estimateReadingTime
blog.test.ts # getAllBlogPosts, getBlogPostBySlug (with fixture files)
memos.test.ts # getAllPublicMemos, getMemoThread, getRelatedBlogPosts
Test fixtures: Create small test markdown files under src/lib/__tests__/fixtures/ for predictable test data.
5.2 Component tests
src/components/blog/__tests__/
BlogCard.test.tsx
TableOfContents.test.tsx
src/components/memos/__tests__/
MemoCard.test.tsx
RoleBadge.test.tsx
src/components/common/__tests__/
AiDisclaimer.test.tsx # (move existing test)
5.3 Page tests
src/app/blog/__tests__/
page.test.tsx # Blog listing renders
src/app/memos/__tests__/
page.test.tsx # Memo listing renders
Step 6: Documentation Updates
- Update
docs/memo-spec.mdto document thepublicfield - Update
docs/architecture.mdto list blog and memo archive sections - Update
docs/index.mdif new docs are created - No new documentation files needed beyond the memo spec update
Complete File Tree (New and Modified Files)
src/
content/
blog/
2026-02-14-how-we-built-this-site.md # NEW - seed post 1
2026-02-14-content-strategy-decision.md # NEW - seed post 2
lib/
markdown.ts # NEW - shared markdown utilities
blog.ts # NEW - blog data layer
memos.ts # NEW - memo archive data layer
seo.ts # MODIFIED - add blog/memo metadata generators
__tests__/
markdown.test.ts # NEW
blog.test.ts # NEW
memos.test.ts # NEW
fixtures/ # NEW - test fixtures directory
sample-blog-post.md
sample-memo.md
app/
blog/
layout.tsx # NEW
page.tsx # NEW - blog listing
page.module.css # NEW
[slug]/
page.tsx # NEW - blog post page
page.module.css # NEW
__tests__/
page.test.tsx # NEW
memos/
layout.tsx # NEW
page.tsx # NEW - memo listing
page.module.css # NEW
[id]/
page.tsx # NEW - individual memo
page.module.css # NEW
thread/
[id]/
page.tsx # NEW - thread view
page.module.css # NEW
__tests__/
page.test.tsx # NEW
page.tsx # MODIFIED - add blog/memo links
sitemap.ts # MODIFIED - add blog/memo URLs
components/
common/
AiDisclaimer.tsx # NEW (shared version)
AiDisclaimer.module.css # NEW (shared version)
Header.tsx # MODIFIED - add nav links
blog/
BlogCard.tsx # NEW
BlogCard.module.css # NEW
BlogPostLayout.tsx # NEW
BlogPostLayout.module.css # NEW
TableOfContents.tsx # NEW
TableOfContents.module.css # NEW
CategoryFilter.tsx # NEW (client component)
CategoryFilter.module.css # NEW
TagList.tsx # NEW
TagList.module.css # NEW
RelatedMemos.tsx # NEW
RelatedMemos.module.css # NEW
__tests__/
BlogCard.test.tsx # NEW
TableOfContents.test.tsx # NEW
memos/
MemoCard.tsx # NEW
MemoCard.module.css # NEW
MemoDetail.tsx # NEW
MemoDetail.module.css # NEW
MemoThreadView.tsx # NEW
MemoThreadView.module.css # NEW
RoleBadge.tsx # NEW
RoleBadge.module.css # NEW
MemoFilter.tsx # NEW (client component)
MemoFilter.module.css # NEW
RelatedBlogPosts.tsx # NEW
RelatedBlogPosts.module.css # NEW
__tests__/
MemoCard.test.tsx # NEW
RoleBadge.test.tsx # NEW
scripts/
memo/
types.ts # MODIFIED - add public field
core/
parser.ts # MODIFIED - parse public field
frontmatter.ts # MODIFIED - serialize public field
commands/
create.ts # MODIFIED - accept --public flag
memo.ts # MODIFIED - pass --public flag
docs/
memo-spec.md # MODIFIED - document public field
architecture.md # MODIFIED - add blog/memo sections
Implementation Order (for builder)
The steps must be implemented in this order due to dependencies:
- Step 1.1-1.2: Shared infrastructure (markdown utils, AiDisclaimer promotion)
- Step 1.3: SEO utility extensions
- Step 2.2: Blog library (
src/lib/blog.ts) - Step 3.2: Memo CLI tool updates (
publicfield) - Step 3.3: Memo archive library (
src/lib/memos.ts) - Step 5.1: Unit tests for libraries (markdown, blog, memos)
- Step 2.3-2.4: Blog pages and components
- Step 2.5: Seed blog content
- Step 3.4-3.5: Memo archive pages and components
- Step 4: Cross-linking integration
- Step 1.4-1.5: Header nav update, sitemap update
- Step 5.2-5.3: Component and page tests
- Step 6: Documentation updates
- Step 4.3: Home page update
Steps 7-8 (blog) and 9 (memos) can be parallelized by separate builder instances since they work on different directories.
Commit checkpoints: The builder should commit after each numbered step (or group of related steps) to enable granular rollback.
Acceptance Criteria
-
npm run buildsucceeds with zero errors -
npm run lintpasses with zero warnings -
npm run typecheckpasses -
npm run format:checkpasses -
npm run testpasses with all new tests green -
/blogpage renders a listing of published blog posts -
/blog/[slug]renders individual blog posts with TOC, reading time, metadata -
/memospage renders a listing of public memos with role badges -
/memos/[id]renders individual memos with thread context -
/memos/thread/[id]renders a full thread view - Blog posts link to related memos via
/memos/[id] - Memo pages link back to blog posts that reference them
- Memos with
public: falseare excluded from the archive - Memos with absent
publicfield default to visible - Secret pattern detection excludes suspicious memos and logs a warning
- AI disclaimer appears on all blog and memo pages (Constitution Rule 3)
- JSON-LD structured data (Article schema) is present on blog post and memo pages
- Blog posts and public memos appear in sitemap.xml
- Header navigation includes "ブログ" and "メモ" links
- All pages are mobile responsive (test at 375px width)
- Category/tag filtering works on blog listing page
- Role/tag filtering works on memo listing page
-
npm run memo create --public falsecreates a memo withpublic: falsein frontmatter - At least 2 seed blog posts exist and render correctly
- No new external npm dependencies are added (unless markdown rendering requires
markedas fallback)
Required Artifacts
Documents to update
docs/memo-spec.md-- addpublicfield documentationdocs/architecture.md-- add blog and memo archive sections
Code to create
- All files listed in the "Complete File Tree" section above
Content to create
- 2 seed blog posts in
src/content/blog/
Rollback Approach
All changes are additive (new files and directories). Rollback is straightforward:
Full rollback:
git revertthe commits in reverse order. No existing functionality is broken because no existing files are deleted (only modified: Header, sitemap, seo.ts, home page, memo CLI).Partial rollback (blog only or memos only): Each feature is in its own directory (
src/app/blog/,src/app/memos/,src/components/blog/,src/components/memos/). Remove the relevant directories and undo the shared file modifications.Memo CLI rollback: The
publicfield is optional with backward compatibility. Removing it requires only reverting the CLI changes; existing memos without the field continue to work.
Constraints
- Must comply with
docs/constitution.md(immutable). - Must follow existing architectural patterns (SSG, CSS modules, no database).
- Must not add external npm dependencies unless explicitly justified.
- TypeScript strict mode must be satisfied.
- All content must be in Japanese.
- Blog post content must include AI experiment disclosure per Constitution Rule 3.
- No user authentication or accounts (architecture principle 2).
Notes
Risks
- Markdown rendering quality: A custom markdown-to-HTML converter may have edge cases. The builder should test against the actual memo content (which uses YAML frontmatter, headings, lists, code blocks, and links). If quality is insufficient,
markedis a reasonable fallback. - Build time: Scanning 63+ memo files at build time should be fast (sub-second), but if the memo count grows to thousands, a caching layer may be needed. Not a concern now.
- Content creation burden: The 2 seed blog posts establish the pattern. Ongoing blog content creation is a separate process concern (who writes posts, how often). This plan only covers the infrastructure.
Assumptions
- Blog posts are authored by agents (not users) and committed to the repo.
- All existing memos are safe to publish publicly (confirmed by researcher).
- The
memo/directory structure and frontmatter format are stable.
Future enhancements (not in scope)
- RSS feed for blog
- Full-text search across blog and memos
- Auto-generated blog summaries from memo threads
- Pagination for large listing pages
- Social sharing buttons on blog posts
- Reading progress indicator