> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase13-session04-content-collections-and-publishing-templates/spec.md).

# Session Specification

**Session ID**: `phase13-session04-content-collections-and-publishing-templates` **Phase**: 13 - Public Website Foundation **Status**: Completed **Created**: 2026-06-01 **Package**: public-website **Package Stack**: Astro 6.4.2 / TypeScript 5.9.3 static site

***

## 1. Session Overview

This session turns the static public website shell into a durable publishing surface. Sessions 01-03 established the Astro workspace, shared visual shell, metadata plumbing, sitemap integration, and a valid RSS scaffold. Session 04 adds typed blog and news content collections, reusable article components, list/detail templates, and seed content that can validate the publishing pipeline before the broader page-building phases begin.

The work matters because Phase 14 and Phase 15 need content routes that already handle schema validation, draft exclusion, metadata, RSS output, sitemap discovery, and realistic FactionOS copy. Blog and news entries should present the product as local-first AI coding agent mission control without implying hosted identity, analytics capture, production-hosted validation, trusted erasure, formal certification, CMS behavior, or hosted form handling.

The session remains static-site-only. It does not introduce a CMS, search, runtime analytics, hosted forms, auth, server-rendered routes, generated social images, or final editorial calendar work. It prepares the reusable publishing surface and enough seed content to prove templates, metadata, tags, RSS, and draft filtering.

***

## 2. Objectives

1. Define typed `blog` and `news` content collections with shared frontmatter validation and news-specific category/version fields.
2. Create reusable content components and an article layout for collection indexes, detail pages, post metadata, tags, draft labels, and related posts.
3. Add realistic seed blog and news entries that validate routes, RSS, sitemap, metadata, tag rendering, and no-overclaim product copy.
4. Wire blog/news list routes, dynamic detail routes, and RSS output so production builds exclude drafts while development templates can show draft badges.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase13-session01-astro-scaffold-and-workspace-wiring` - Provides the Astro workspace, npm workspace scripts, MDX support, sitemap integration, RSS dependency, and static output posture.
* [x] `phase13-session02-design-tokens-and-layout-shell` - Provides shared shell, navigation, layout primitives, system components, global styles, and responsive design foundation.
* [x] `phase13-session03-seo-metadata-and-static-site-plumbing` - Provides central site data, SEO/JSON-LD components, metadata helpers, robots, manifest, sitemap posture, and an RSS route scaffold.

### Required Tools/Knowledge

* Astro 6 content collections through `src/content.config.ts`.
* `astro:content` collection querying, dynamic route `getStaticPaths`, and content rendering.
* `astro/zod` frontmatter schema validation, including optional image fields.
* `@astrojs/rss` feed generation from static collection entries.
* Project conventions for npm workspaces, Biome, TypeScript, ASCII-only files, and static public website boundaries.

### Environment Requirements

* Node.js 26.2.0 or newer and npm 11.16.0 per repository baseline.
* On this machine, prepend `/home/aiwithapex/.nvm/versions/node/v26.2.0/bin` to `PATH` before package commands if the default shell resolves Node 24.
* Run validation from the repository root or with `--workspace @factionos/public-website`.

***

## 4. Scope

### In Scope (MVP)

* Site maintainers can add blog and news content with typed frontmatter - Implement `public-website/src/content.config.ts` for `blog` and `news`.
* Build-time validation rejects invalid publishing metadata - Use Astro/Zod schemas for titles, descriptions, dates, draft flags, tags, optional hero images, canonical URLs, authors, news categories, and versions.
* Visitors can browse blog posts and news/changelog entries - Create list routes with deterministic sorting, empty states, tags, and accessible cards.
* Visitors can read individual blog and news entries - Create dynamic routes using a shared article layout, metadata, draft badges in development, and related-post affordances.
* Feed consumers can subscribe to current publishing output - Update RSS to include only non-draft blog/news entries with absolute URLs and concise descriptions.
* Crawlers can discover collection routes through static output - Ensure list and detail routes build with sitemap-compatible paths.
* Seed content can validate templates without placeholder copy - Add three blog posts and two news entries with specific FactionOS local-first, cockpit, demo, and publishing foundation content.

### Out of Scope (Deferred)

* Full editorial calendar - *Reason: this session validates the publishing mechanism, not long-term content operations.*
* Search - *Reason: searchable content needs separate UX, indexing, and privacy review.*
* CMS integration - *Reason: first release remains static with no CMS adapter or hosted authoring surface.*
* Tag archive pages - *Reason: tags can render on entries and cards first; archive routing can wait until content volume justifies it.*
* Generated social images - *Reason: Session 05 owns approved brand media and Open Graph asset promotion.*
* Final polished blog/news strategy - *Reason: Phase 15 owns broader content and conversion page polish.*

***

## 5. Technical Approach

### Architecture

The website remains a static Astro package. `src/content.config.ts` defines the `blog` and `news` collections with Astro/Zod schemas and glob loaders rooted in `src/content/blog` and `src/content/news`. Shared content helpers under `src/lib/content.ts` normalize draft filtering, date sorting, reading-time estimation, absolute URL generation, and related-entry selection so routes and RSS use the same rules.

List routes query collections, filter drafts in production, sort newest first, and render reusable cards with tags and metadata. Dynamic routes use `getStaticPaths` to emit static post pages, render Markdown/MDX content through Astro, and pass article metadata to the Session 03 SEO layer. Blog posts should emit BlogPosting-style structured data; news entries should emit NewsArticle structured data where the fields are available.

RSS updates the Session 03 scaffold to read non-draft collection entries and emit a combined feed. The feed must use absolute URLs, deterministic ordering, and concise descriptions. All routes remain serverless/static, with no analytics, no CMS, no auth, no hosted forms, no dynamic personalization, and no third-party tracking.

### Design Patterns

* Content schema first: Validate frontmatter before templates consume it.
* Shared query helpers: Keep draft filtering, sorting, and URL generation consistent across routes and RSS.
* Componentized publishing UI: Reuse post cards, metadata, tag lists, collection heroes, related posts, and article layout instead of route-local markup.
* Static route safety: Use Astro `getStaticPaths` and build-time collection queries rather than runtime fetches.
* Claim boundaries: Seed copy must stay source-backed and avoid unsupported hosted, analytics, erasure, certification, or media-readiness claims.

### Technology Stack

* Astro: 6.4.2
* `@astrojs/mdx`: 6.0.1
* `@astrojs/rss`: 4.0.18
* `@astrojs/sitemap`: 3.7.3
* TypeScript: 5.9.3
* Vite: 7.3.5
* Biome: root formatting and linting

***

## 6. Deliverables

### Files to Create

| File                                                                 | Purpose                                                                       | Est. Lines |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------- |
| `public-website/src/content.config.ts`                               | Typed blog/news collection schemas and loaders                                | \~90       |
| `public-website/src/lib/content.ts`                                  | Shared draft filtering, sorting, reading time, URL, and related-entry helpers | \~130      |
| `public-website/src/components/content/CollectionHero.astro`         | Reusable collection header with count/empty state support                     | \~70       |
| `public-website/src/components/content/PostCard.astro`               | Accessible blog/news preview card with tags and metadata                      | \~120      |
| `public-website/src/components/content/PostMeta.astro`               | Date, author, category, version, and reading-time metadata component          | \~90       |
| `public-website/src/components/content/TagList.astro`                | Deterministic tag list component with accessible labels                       | \~60       |
| `public-website/src/components/content/RelatedPosts.astro`           | Bounded related-entry affordance for detail pages                             | \~90       |
| `public-website/src/layouts/PostLayout.astro`                        | Shared article layout with SEO, JSON-LD, draft badge, tags, and content slot  | \~150      |
| `public-website/src/pages/blog/index.astro`                          | Blog listing route                                                            | \~100      |
| `public-website/src/pages/blog/[...slug].astro`                      | Blog dynamic detail route                                                     | \~120      |
| `public-website/src/pages/news/index.astro`                          | News/changelog listing route                                                  | \~100      |
| `public-website/src/pages/news/[...slug].astro`                      | News dynamic detail route                                                     | \~130      |
| `public-website/src/content/blog/introducing-factionos.md`           | Seed launch blog entry                                                        | \~70       |
| `public-website/src/content/blog/local-first-agent-observability.md` | Seed local-first architecture blog entry                                      | \~80       |
| `public-website/src/content/blog/why-agent-work-needs-a-cockpit.md`  | Seed cockpit/product thinking blog entry                                      | \~80       |
| `public-website/src/content/news/initial-public-website.md`          | Seed website foundation news entry                                            | \~55       |
| `public-website/src/content/news/public-demo-available.md`           | Seed public demo news entry                                                   | \~55       |

### Files to Modify

| File                                  | Changes                                                       | Est. Lines |
| ------------------------------------- | ------------------------------------------------------------- | ---------- |
| `public-website/src/pages/rss.xml.js` | Replace empty scaffold with combined non-draft blog/news feed | \~75       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Blog and news indexes render from typed content collections.
* [ ] Blog and news dynamic post routes render static pages.
* [ ] Invalid frontmatter fails schema validation during typecheck or build.
* [ ] Draft entries are excluded from production output and RSS.
* [ ] Development templates can show a visible draft badge without leaking drafts into production builds.
* [ ] RSS builds with non-draft blog and news content and absolute item links.
* [ ] Seed content is specific to FactionOS and avoids lorem ipsum or generic SaaS filler.
* [ ] Collection pages and detail pages use Session 03 metadata and structured data without unsupported product claims.

### Testing Requirements

* [ ] Package typecheck passes.
* [ ] Package build passes.
* [ ] Focused Biome lint/format checks pass for touched website and session files.
* [ ] Generated `dist` blog, news, RSS, and sitemap artifacts are inspected.

### Non-Functional Requirements

* [ ] Static Astro output remains the deployment model.
* [ ] No analytics, trackers, hosted forms, auth, CMS adapter, React, Tailwind, shadcn/ui, server adapter, or runtime personalization is added.
* [ ] List and related-post outputs are bounded and deterministically ordered.
* [ ] Templates remain responsive, keyboard-accessible, and readable at mobile widths.
* [ ] Copy preserves local-first, no-overclaim, and external-link boundaries.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.

***

## 8. Implementation Notes

### Key Considerations

* `public-website/src/pages/rss.xml.js` currently contains a valid empty feed scaffold from Session 03 and should be wired to collections here.
* `public-website/src/layouts/ContentLayout.astro`, `BaseLayout.astro`, and the SEO components already support route metadata, canonical paths, article Open Graph type, and structured data inputs.
* The footer navigation already links to `/blog` and `/news`; this session should make those routes real without broadening the primary navigation.
* Use component-scoped CSS for content components where possible, adding global prose rules only when shared article typography truly belongs in the global layer.
* Hero image fields should remain optional. Do not promote unknown or unreviewed brand/showcase media before Session 05 asset work.

### Potential Challenges

* Astro content API drift: Use the Astro 6 content layer pattern already supported by the installed package versions.
* Draft filtering consistency: Centralize production/non-production behavior so indexes, dynamic paths, related posts, and RSS cannot diverge.
* RSS route typing from JavaScript: Keep the existing route if simple, or convert only if needed for a clean typed import path.
* Seed copy overclaim: Keep articles short, concrete, and aligned with the PRD boundaries instead of making launch, hosted, analytics, or certification claims.
* Sitemap expectations: Astro sitemap should discover generated routes after a successful static build; inspect output rather than assuming coverage.

### Relevant Considerations

* \[P04] **Asset provenance gate remains active**: Hero images stay optional and no unknown media should be promoted before Session 05.
* \[P07] **Hosted services ship as disabled-default guardrails only**: Blog/news copy must not imply active hosted auth, hosted storage, analytics capture, push, remote access, or hosted collaboration.
* \[P07] **Redaction is boundary-specific**: Seed content should not suggest prompts, local paths, commands, terminal output, replay buffers, exports, diagnostics, logs, or backups leave the local machine by default.
* \[P08] **Release-candidate evidence is claim-scoped**: Static build success is not production-hosted validation, formal certification, trusted erasure, or broad media readiness.
* \[P02-apps/web] **Responsive and accessibility debt**: Content cards, tags, article metadata, and related-post affordances need semantic markup, focus visibility, and mobile wrapping.
* \[P03] **Stable docs are the current contract**: Seed content should reference current docs-facing behavior, not archived phase history or evidence-only materials.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Draft entries accidentally appearing in production routes, RSS, or sitemap output.
* Invalid or incomplete frontmatter reaching templates without schema failure.
* Blog/news copy overclaiming hosted services, analytics, erasure, certification, production validation, or media readiness.
* Content cards, tag lists, and related posts becoming inaccessible or unstable at small viewport widths.

***

## 9. Testing Strategy

### Unit Tests

* No new Vitest unit tests are required unless helper logic becomes complex. Keep content helper functions small and validate them through typecheck/build.

### Integration Tests

* Run `npm --workspace @factionos/public-website run typecheck`.
* Run `npm --workspace @factionos/public-website run build`.
* Run focused Biome checks for touched files.

### Manual Testing

* Inspect generated `dist/blog/index.html`, at least one blog detail page, `dist/news/index.html`, at least one news detail page, `dist/rss.xml`, and generated sitemap output.
* Confirm draft behavior by code review and, if a draft fixture is added for testing, verify it does not appear in production build output.
* Confirm external demo/docs links remain explicit and no hosted forms or analytics scripts are present.

### Edge Cases

* Empty collection lists should render an intentional empty state.
* Entries with no tags should avoid empty tag chrome.
* Entries with no hero image should render readable article pages without broken media.
* Optional `updatedDate`, `author`, `category`, and `version` fields should render only when present.
* Related posts should be bounded, deterministic, and omit the current entry.

***

## 10. Dependencies

### External Libraries

* Astro: 6.4.2
* `@astrojs/mdx`: 6.0.1
* `@astrojs/rss`: 4.0.18
* `@astrojs/sitemap`: 3.7.3
* TypeScript: 5.9.3
* Vite: 7.3.5

### Other Sessions

* **Depends on**: `phase13-session01-astro-scaffold-and-workspace-wiring`, `phase13-session02-design-tokens-and-layout-shell`, `phase13-session03-seo-metadata-and-static-site-plumbing`
* **Depended by**: `phase13-session05-asset-pipeline-and-brand-media-prep`, Phase 14 page build sessions, and Phase 15 content/conversion polish sessions

***

## Next Steps

Run the implement workflow step to begin AI-led implementation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase13-session04-content-collections-and-publishing-templates/spec.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
