63 lines
2.9 KiB
Markdown
63 lines
2.9 KiB
Markdown
## Context
|
|
|
|
The site renders multiple card-like UI elements today:
|
|
- videos/podcast listings use `site/src/components/ContentCard.astro`
|
|
- blog listings use `site/src/components/BlogPostCard.astro`
|
|
|
|
These cards have different layouts and metadata placement. This change standardizes the card information architecture so all cards feel consistent.
|
|
|
|
The site is statically generated (Astro). Card layout consistency should be enforced primarily through shared components and shared CSS rather than copy/paste per page.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
|
|
- Define and implement a single, consistent card structure:
|
|
- media (image/placeholder) at top
|
|
- title
|
|
- trimmed summary/excerpt
|
|
- meta row: date (left) + views (right, if available)
|
|
- footer: source label (youtube/podcast/blog/etc.)
|
|
- Apply to all existing card surfaces:
|
|
- `/videos` listing cards
|
|
- `/podcast` listing cards
|
|
- `/blog` post cards (and category listings)
|
|
- Keep the layout resilient when fields are missing (no views, no image, no summary).
|
|
|
|
**Non-Goals:**
|
|
|
|
- Redesigning non-card list links (e.g., simple navigation links) into cards unless needed for consistency.
|
|
- Changing Umami tracking taxonomy (attributes stay intact).
|
|
- Large typographic or theme redesign beyond card structure/spacing.
|
|
|
|
## Decisions
|
|
|
|
- **Decision: Implement a shared Card component used by existing card components.**
|
|
- Rationale: Centralizes markup and ensures layout stays consistent across surfaces.
|
|
- Approach:
|
|
- Create a new component (e.g., `Card.astro`) with props for:
|
|
- `href`, `title`, `summary`, `imageUrl`, `dateLabel`, `viewsLabel`, `sourceLabel`
|
|
- optional tracking attributes pass-through (keep existing `data-umami-*` behavior)
|
|
- Update `ContentCard.astro` and `BlogPostCard.astro` to render the shared Card component.
|
|
|
|
- **Decision: Add an optional `summary` field to normalized items.**
|
|
- Rationale: Enables the standard card layout to show trimmed summaries for videos/podcast, similar to blog excerpts.
|
|
- Approach:
|
|
- Extend the normalized content schema/types with `summary?: string`.
|
|
- Populate it during ingestion where available (YouTube description snippet; podcast episode summary/description).
|
|
|
|
- **Decision: Views are optional and shown only when available.**
|
|
- Rationale: Not all sources provide views; the layout should be consistent without forcing synthetic values.
|
|
|
|
## Risks / Trade-offs
|
|
|
|
- [Risk] Ingestion sources may provide very long summaries.
|
|
- Mitigation: Standardize trimming logic in the card component (single truncation helper).
|
|
|
|
- [Risk] CSS regressions across multiple pages.
|
|
- Mitigation: Add tests that assert key card structure/classes exist; verify build outputs for `/videos`, `/podcast`, `/blog`.
|
|
|
|
- [Risk] Blog post cards and content cards have different link targets (internal vs outbound).
|
|
- Mitigation: Shared Card component should be able to render both internal links and external links (target/rel configurable).
|
|
|