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-resolutioncollection 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-resolutioncollection. - 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
collectionPublishingDefaultsand individual entrypublishflags.
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.astroto 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.astrocomponent. - 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
slugand a base path (hardcoded toissue-resolution). - Uses
formatDateutility for consistent date presentation. - Debug
console.logfordescriptionprop was removed.
site/src/pages/learn-with/[collection]/[...slug].astro:- Dynamic route for displaying individual articles from specified collections.
getStaticPathsgenerates paths forissue-resolutionentries, creating slugs from article titles.- Passes article content (
entry.body) and metadata to theOneArticlelayout, which usesOneArticleOnPagefor rendering. - Normalizes frontmatter data (dates, authors, tags, categories) for consistent presentation.
Modified Files
site/src/components/articles/PostCard--Bare.astro:- Removed a
console.logstatement used for debugging thedescriptionprop. This was located immediately after prop destructuring.
Technical Details
Data Flow for issue-resolution Collection:
- Content Definition (
site/src/content/config.ts): Theissue-resolutioncollection 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
collectionPublishingDefaultsand individualpublishflags. entry.datais mapped to anarticlesarray. 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
articlesarray,pageTitle, andpageDescriptionare passed toMagazineIndexLayout.astro.
- Layout for Index (
site/src/layouts/MagazineIndexLayout.astro):- Renders a header with
collectionDisplayNameanddescription. - Passes the
articlesarray toArticleGrid.astro.
- Grid Display (
site/src/components/articles/ArticleGrid.astro):- Iterates through the
articlesarray. - For each article, it maps fields to props for
PostCard--Bare.astro:slugmaps toslug.banner_imageorportrait_imagemaps toimageSrc.titlemaps totitle.datemaps todate.ledemaps todescription.
- Card Display (
site/src/components/articles/PostCard--Bare.astro):- Renders the individual article card.
- Link
hrefis 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):getStaticPathsgenerates a path for each published article inissue-resolutionusingslugify(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
entryandcollectionname as props. entry.datais processed to preparearticleData(title, date, authors, tags, categories, banner_image, lede).entry.body(raw Markdown content) andarticleDataare passed to theOneArticlelayout, which usesOneArticleOnPagefor rendering.
Styling and Layout:
- The
MagazineIndexLayout.astrointroduces specific styles for a header and container to achieve a magazine-like feel. PostCard--Bare.astroincludes Tailwind CSS classes for styling the card, image, and text elements.ArticleGrid.astrouses 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.astrofor consistent date display.normalizeToArrayfunction (insite/src/pages/learn-with/us.astroandsite/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-levelpublishflag 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-resolutioncollection 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.tsandformatDate.tsbeing 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.mdoutlines the initial requirements and plan. - The schema for
issue-resolutionentries should be clearly defined insite/src/content/config.tsor accompanying documentation for content creators.