Integrate 'issue-resolution' Collection with Magazine Layout
Summary
This changelog details the integration of the
issue-resolution
content collection into the site. It includes the creation of new Astro components, layouts, and pages to support a magazine-style presentation for these articles, along with dynamic routing for individual article views.Why Care
This integration establishes a dedicated pathway for presenting detailed issue resolutions, improving knowledge sharing and providing a structured format for documenting problem-solving processes. The magazine layout enhances readability and user engagement, making it easier to consume technical content.
Implementation
Changes Made
New Files Created
The following files were created to support the
issue-resolution
collection and its presentation:site/src/content/config.ts
: (Implicitly modified) Theissue-resolution
collection was defined here, enabling Astro to recognize and process its content.site/src/pages/learn-with/us.astro
:- Serves as the index page for collections under
/learn-with/
. - Currently hardcoded to fetch and display entries from the
issue-resolution
collection. - Transforms raw collection data into a format suitable for
ArticleGrid.astro
, including slug generation, date normalization, and handling of array-based frontmatter fields (tags, authors, categories). - Implements publishing logic based on
collectionPublishingDefaults
and individual entrypublish
flags.
site/src/layouts/MagazineIndexLayout.astro
:- Provides the primary layout for collection index pages like
/learn-with/us
. - Receives article data and page metadata (title, description) as props.
- Uses
ArticleGrid.astro
to display the articles. - Includes styling for a clean, magazine-like header and content area.
site/src/components/articles/ArticleGrid.astro
:- Renders a responsive grid of article previews.
- Accepts an array of processed article data.
- Maps article data to props for the
PostCard--Bare.astro
component. - Handles passthrough attributes for flexibility.
site/src/components/articles/PostCard--Bare.astro
:- Displays individual article previews (image, title, date, lede).
- Constructs article links dynamically using the
slug
and a base path (hardcoded toissue-resolution
). - Uses
formatDate
utility for consistent date presentation. - Debug
console.log
fordescription
prop was removed.
site/src/pages/learn-with/[collection]/[...slug].astro
:- Dynamic route for displaying individual articles from specified collections.
getStaticPaths
generates paths forissue-resolution
entries, creating slugs from article titles.- Passes article content (
entry.body
) and metadata to theOneArticle
layout, which usesOneArticleOnPage
for rendering. - Normalizes frontmatter data (dates, authors, tags, categories) for consistent presentation.
Modified Files
site/src/components/articles/PostCard--Bare.astro
:- Removed a
console.log
statement used for debugging thedescription
prop. This was located immediately after prop destructuring.
Technical Details
Data Flow for issue-resolution
Collection:
- Content Definition (
site/src/content/config.ts
): Theissue-resolution
collection is defined, likely with a schema specifying frontmatter fields (e.g.,title
,lede
,date_reported
,tags
,authors
,banner_image
,publish
). - Index Page (
site/src/pages/learn-with/us.astro
):getCollection('issue-resolution')
fetches all entries.- Entries are filtered based on
collectionPublishingDefaults
and individualpublish
flags. entry.data
is mapped to anarticles
array. Key transformations include:slug
: Generated viaslugify(data.title)
.date
: Normalized fromdate_reported
,date_created
, ordate_modified
.lede
: Taken fromdata.lede
.tags
,authors
,categories
: Normalized to arrays.
- The
articles
array,pageTitle
, andpageDescription
are passed toMagazineIndexLayout.astro
.
- Layout for Index (
site/src/layouts/MagazineIndexLayout.astro
):- Renders a header with
collectionDisplayName
anddescription
. - Passes the
articles
array toArticleGrid.astro
.
- Grid Display (
site/src/components/articles/ArticleGrid.astro
):- Iterates through the
articles
array. - For each article, it maps fields to props for
PostCard--Bare.astro
:slug
maps toslug
.banner_image
orportrait_image
maps toimageSrc
.title
maps totitle
.date
maps todate
.lede
maps todescription
.
- Card Display (
site/src/components/articles/PostCard--Bare.astro
):- Renders the individual article card.
- Link
href
is constructed as/learn-with/issue-resolution/{slug}
. - Displays
imageSrc
,title
,description
(fromlede
), and formatteddate
.
- Individual Article Page (
site/src/pages/learn-with/[collection]/[...slug].astro
):getStaticPaths
generates a path for each published article inissue-resolution
usingslugify(entry.data.title)
.- When a user navigates to
/learn-with/issue-resolution/some-article-slug
, Astro serves the corresponding pre-rendered page. - The page component receives the
entry
andcollection
name as props. entry.data
is processed to preparearticleData
(title, date, authors, tags, categories, banner_image, lede).entry.body
(raw Markdown content) andarticleData
are passed to theOneArticle
layout, which usesOneArticleOnPage
for rendering.
Styling and Layout:
- The
MagazineIndexLayout.astro
introduces specific styles for a header and container to achieve a magazine-like feel. PostCard--Bare.astro
includes Tailwind CSS classes for styling the card, image, and text elements.ArticleGrid.astro
uses Tailwind CSS for a responsive grid layout (1, 2, or 3 columns depending on screen size).
Key Functions & Logic:
slugify
(insite/src/utils/slugify.ts
, assumed): Used to generate URL-friendly slugs from titles.formatDate
(insite/src/utils/formatDate.ts
, assumed): Used inPostCard--Bare.astro
for consistent date display.normalizeToArray
function (insite/src/pages/learn-with/us.astro
andsite/src/pages/learn-with/[collection]/[...slug].astro
): Handles frontmatter fields that can be either a single string or an array of strings, ensuring they are always processed as arrays.- Publishing Logic (in
site/src/pages/learn-with/us.astro
): Filters articles based on a collection-level default (collectionPublishingDefaults
) and an item-levelpublish
flag in the frontmatter. This allows selective publishing of content.
Key Code Snippets
1. Fetching and Transforming Collection Data (
site/src/pages/learn-with/us.astro
)
This snippet shows how entries are fetched, filtered by publishing status, and then mapped to the articles
array with necessary transformations like slug generation and date normalization. astro
---
import { getCollection } from 'astro:content';
import { slugify } from '../../utils/slugify';
import { collectionPublishingDefaults } from '../../content.config';
const collectionName = 'issue-resolution'; // Hardcoded for this page
const allEntriesUnfiltered = await getCollection(collectionName);
// Apply publishing filter
const defaultPublishBehavior = collectionPublishingDefaults[collectionName]?.publishByDefault ?? true;
const allEntries = allEntriesUnfiltered.filter((entry) => {
const itemPublishFlag = (entry.data as Record<string, any>).publish;
return defaultPublishBehavior ? itemPublishFlag !== false : itemPublishFlag === true;
});
const articles = allEntries.map((entry) => {
const data = entry.data as Record<string, any>;
const customSlug = slugify(data.title || 'Untitled Issue');
// ... other transformations for date, tags, etc. ...
return {
id: entry.id,
title: data.title || 'Untitled Issue',
slug: customSlug,
lede: data.lede || '',
// ... other mapped properties ...
};
});
---
<!-- Layout uses `articles` prop -->
2. Dynamic Route Generation (
site/src/pages/learn-with/[collection]/[...slug].astro
)
Illustrates how getStaticPaths
generates static pages for each article in the issue-resolution
collection using a slugified title. astro
---
import { getCollection, type CollectionEntry } from 'astro:content';
import { slugify } from '../../../utils/slugify';
import Layout from '@layouts/Layout.astro';
import OneArticle from '@layouts/OneArticle.astro';
import OneArticleOnPage from '@components/articles/OneArticleOnPage.astro';
export async function getStaticPaths() {
const collectionsToProcess = ['issue-resolution'];
const paths = [];
for (const collectionName of collectionsToProcess) {
const entries = await getCollection(collectionName as any);
for (const entry of entries) {
const titleSlug = slugify(entry.data.title || 'Untitled Issue');
paths.push({
params: { collection: collectionName, slug: titleSlug },
props: { entry, collection: collectionName },
});
}
}
return paths;
}
const { entry, collection } = Astro.props;
const { Content } = await entry.render(); // To render Markdown content
// ... data preparation for articleData ...
---
<Layout title={pageTitle} description={pageDescription}>
<OneArticle
Component={OneArticleOnPage}
content={entry.body} {/* Pass raw Markdown body */}
{/* ... other props ... */}
>
<Content /> {/* Renders the actual article markdown */}
</OneArticle>
</Layout>
3. Article Grid and Card Invocation (
site/src/components/articles/ArticleGrid.astro
)
Shows how ArticleGrid.astro
iterates over processed articles and passes data to PostCard--Bare.astro
. astro
---
import PostCardBare from './PostCard--Bare.astro';
// ... Props interface ...
const { articles, ... } = Astro.props;
---
<div class="grid ...">
{articles.map(p => (
<PostCardBare
slug={p.slug}
imageSrc={p.banner_image || p.portrait_image || '/images/placeholders/default-banner.jpg'}
imageAlt={p.imageAlt}
title={p.title}
date={p.date}
description={p.lede}
{...p.passthroughAttrs}
/>
))}
</div>
4. Basic Card Structure (
site/src/components/articles/PostCard--Bare.astro
)
Highlights the core structure of an individual article card, including dynamic link generation and prop usage. astro
---
import { formatDate } from "@utils/formatDate";
// ... Props interface ...
const {
slug, imageSrc, imageAlt, title, date, description, ...
} = Astro.props;
const collectionBasePath = 'issue-resolution';
const href = `/learn-with/${collectionBasePath}/${slug}`;
const displayDate = date ? formatDate(typeof date === 'string' ? new Date(date) : date) : "";
---
<a href={href} class="flex flex-col group ...">
<div>
<figure>
<img src={imageSrc} alt={imageAlt} ... />
</figure>
</div>
<div>
<h2 class="font-semibold ...">{title}</h2>
{description && <p class="text-sm opacity-80 ...">{description}</p>}
<p class="opacity-70 text-sm ...">{displayDate}</p>
</div>
</a>
Integration Points
site/src/content/config.ts
: This is the central point for defining content collections. The newissue-resolution
collection schema needs to be robust to ensure data integrity.- Navigation: Links to
/learn-with/us
(or/learn-with/issue-resolution
) might need to be added to site navigation menus or sitemaps. - Global Styles: While components are styled locally or with Tailwind, ensure no conflicts arise with existing global CSS.
- Utility Functions: Relies on
slugify.ts
andformatDate.ts
being present and correctly functioning in thesite/src/utils/
directory.
Documentation
- The primary documentation for this integration is this changelog entry and the code comments within the new/modified files.
- The prompt
content/lost-in-public/prompts/render-logic/Integrate-Collection-into-Site.md
outlines the initial requirements and plan. - The schema for
issue-resolution
entries should be clearly defined insite/src/content/config.ts
or accompanying documentation for content creators.