ADR-017: Experience Content Collection
Status
Section titled “Status”Superseded by ADR-027: Content Collections Schema Design, which provides the comprehensive schema design for the five collections it covers (a sixth collection, adr, was added to src/content.config.ts later). This ADR remains the rationale for creating the experience collection.
Context
Section titled “Context”The about.astro page previously hardcoded work experience data in the frontmatter, which:
- Violated DRY principles if experience data needed to be reused (e.g., resume page, homepage)
- Made it difficult to manage rich content (descriptions, achievements)
- Didn’t leverage Astro’s Content Collections API for type safety and validation
Decision
Section titled “Decision”We will create an experience content collection to manage work history data:
- Collection Type:
content(supports MDX for rich descriptions) - Schema: Includes title, company, dates, description, highlights, technologies
- Usage: Optional - can be used on about page or kept as hardcoded data for simplicity
Schema Design
Section titled “Schema Design”const experienceCollection = defineCollection({ type: "content", schema: z.object({ title: z.string(), company: z.string(), location: z.string().optional(), startDate: z.date(), endDate: z.date().optional(), // Optional for current positions current: z.boolean().default(false), description: z.string(), highlights: z.array(z.string()).optional(), technologies: z.array(z.string()).optional(), order: z.number().default(0), // For manual ordering }),});Usage Example
Section titled “Usage Example”Option 1: Use Content Collection (Recommended for Reusability)
Section titled “Option 1: Use Content Collection (Recommended for Reusability)”---import { getCollection } from 'astro:content';
const experiences = await getCollection('experience');const sortedExperiences = experiences .sort((a, b) => a.data.order - b.data.order);---
{sortedExperiences.map((exp) => ( <article> <h3>{exp.data.title}</h3> <p>{exp.data.company}</p> <p>{exp.data.description}</p> </article>))}Option 2: Keep Hardcoded (Acceptable for Single Use)
Section titled “Option 2: Keep Hardcoded (Acceptable for Single Use)”If experience data is ONLY used on the about page and won’t be reused elsewhere, hardcoded data is acceptable per YAGNI principle.
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- Type Safety: Zod schema validation ensures data integrity
- Reusability: Experience data can be used across multiple pages
- Rich Content: MDX support allows detailed descriptions with formatting
- Maintainability: Separate content files are easier to manage than frontmatter
- Flexibility: Can add fields (e.g., company logo, links) without code changes
Negative
Section titled “Negative”- Complexity: Adds overhead if only used in one place
- Build Time: Slight increase in build time for content processing
Neutral
Section titled “Neutral”- Migration: Existing hardcoded data can remain until reuse is needed
- Backward Compatible: Both approaches can coexist
Implementation Notes
Section titled “Implementation Notes”- Date Formatting: Use helper functions to format dates (e.g., “2022 - Present”)
- Ordering: Use
orderfield for manual sorting (lower numbers first) - Current Position: Use
current: trueand omitendDatefor current roles - Technologies: Store as array for Badge component rendering
Related ADRs
Section titled “Related ADRs”- ADR 000: Starter Decisions (Content Collections usage)
- ADR 003: Unified Component Structure (atomic design pattern; the planned “ADR-016: Badge Component” was never written — see the 016 stub)
References
Section titled “References”Enforcement
Section titled “Enforcement”Not enforced — this record’s status is Superseded; only Accepted ADRs are binding (see the status table in the ADR README and ADR-039).
Date: 2025-10-01 (footer backfilled 2026-07-05 from git history; this record predates the footer convention)
Participants: Template maintainers
Outcome: Superseded by ADR-027