Implementation Spec: Spotify-Style Documentation Browser
Context
You're working on a markdown blog server that currently displays 27 markdown files in a flat list. The goal is to transform it into a Spotify-like documentation browser with:
- Homepage: "Your Library" view with recently added docs
- Library Page: Organized by categories (like genres/playlists in Spotify)
- Metadata system: Frontmatter in each markdown file for categorization
- Dark mode: Already implemented, keep it
- PWA support: Already implemented, keep it
Current State
Location: /home/ubuntu/yap/
Key files:
server.js- Express server serving markdown files from root directory- 27
.mdfiles in root directory (mix of personal letters, technical docs, stories, design docs) manifest.json,sw.js- PWA files (don't touch)public/icon.svg- App icon (don't touch)
Current behavior:
- Homepage (
/) lists all 27 docs in a flat unordered list - Individual doc pages (
/:filename) render markdown with back link - Dark mode support via CSS media queries
- Service worker registration on all pages
What to Build
1. Add Frontmatter to All Markdown Files
Add YAML frontmatter to the top of each .md file following this structure:
---
title: "Human-readable title"
category: "Category Name"
repo: "yap"
dateAdded: "2025-11-04"
tags: ["tag1", "tag2"]
---
Categories to use:
Personal- Letters to future self/partnerSystem- Phone system reference, blog posts about The SysStories- Educational debugging narratives (disk detective, swap memory, etc.)Design- Technical design docs and architecture planningMeta- Reflections, feedback, ideas (learning feed, performance reviews)Setup- README, installation guides, PWA setup
Files and their categories:
Personal:
- letter-to-future-partner-early-dating.md
- letter-to-future-partner-getting-serious.md
- letter-to-future-self-doubting.md
- letter-to-future-self-proud.md
System:
- phone-system-reference.md
- blog-post-ssh-to-sanity.md
Stories:
- disk-detective-story.md
- tale-of-two-ports.md
- the-case-of-the-unresponsive-enter-key.md
- understanding-swap-memory.md
Design:
- cmd-exec-design-v0.md
- cmd-exec-design-v1.md
- chat-app-testing-strategy.md
- design-doc.md
- e2e-testing-strategy-git-chat.md
- imessage-vanilla-ui-design.md
- pwa-ios-native-feel.md
- disk-detective-story-plan.md
- streaming-execution-progress.md
Meta:
- feedback-pair-programming-session.md
- note-to-next-agent.md
- performance-review.md
- learning-feed-idea.md
Setup:
- PWA-SETUP.md
- README.md
- dev-vs-prod-resources.md
- what-best-tech-readings.md
Notes:
- Use file's existing first heading as the
titleif present, otherwise derive from filename - All files have
repo: "yap"for now - Use
dateAdded: "2025-11-04"for all (we'll update later with real git dates) - Tags can be inferred from content or left as
[]for now
2. Update server.js to Parse Frontmatter
Add dependency: Install gray-matter to parse frontmatter
npm install gray-matter
Update file reading logic:
const matter = require('gray-matter');
// When reading a markdown file:
const fileContent = fs.readFileSync(filepath, 'utf-8');
const { data, content } = matter(fileContent);
// data = frontmatter object
// content = markdown without frontmatter
Create helper function:
function getAllDocsWithMetadata() {
return fs.readdirSync(__dirname)
.filter(file => file.endsWith('.md'))
.map(file => {
const filepath = path.join(__dirname, file);
const fileContent = fs.readFileSync(filepath, 'utf-8');
const { data } = matter(fileContent);
return {
filename: file,
path: `/${file}`,
...data // spread frontmatter fields
};
})
.sort((a, b) => {
// Sort by dateAdded, most recent first
return new Date(b.dateAdded) - new Date(a.dateAdded);
});
}
3. Build Homepage - "Your Library" View
Route: GET /
Design: Spotify-inspired dark interface
Layout:
┌─────────────────────────────────────┐
│ 🎵 The Sys. │
├─────────────────────────────────────┤
│ Your Library [Library →] │
│ │
│ Recently Added │
│ ┌─────────────────────────────┐ │
│ │ 📄 Learning Feed Idea │ │
│ │ Meta • yap • 2025-11-04 │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ 📄 PWA Setup │ │
│ │ Setup • yap • 2025-11-04 │ │
│ └─────────────────────────────┘ │
│ ... (show top 10) │
└─────────────────────────────────────┘
Key elements:
- Header with app name and "Library" link
- "Recently Added" section showing 10 most recent docs
- Each doc card shows:
- Icon based on category (📝 Personal, 📖 Stories, ⚙️ Design, 💭 Meta, 📄 Setup, 🔧 System)
- Title from frontmatter
- Subtitle: "Category • Repo • Date"
- Clickable → navigates to doc
CSS styling:
- Dark background (
#121212like Spotify) - Card-based layout
- Hover effects (slight elevation/glow)
- Clean typography (use existing font stack)
4. Build Library Page - Categorized View
Route: GET /library
Design: Organized by category, all 27 docs visible
Layout:
┌─────────────────────────────────────┐
│ 🎵 The Sys. [Home ←] │
├─────────────────────────────────────┤
│ Library │
│ │
│ Personal (4) │
│ • Letter to future self (proud) │
│ • Letter to future self (doubting) │
│ • Letter to future partner (early) │
│ • Letter to future partner (serious)│
│ │
│ System (2) │
│ • Phone system reference │
│ • The Laptop I Gave Away │
│ │
│ Stories (4) │
│ ... (and so on for all categories) │
└─────────────────────────────────────┘
Key elements:
- Header with "Home" back link
- Each category as collapsible section (or always expanded for simplicity)
- List all docs under each category
- Show count in category header
- Clicking doc navigates to it
Group by logic:
function groupDocsByCategory(docs) {
const grouped = {};
docs.forEach(doc => {
const category = doc.category || 'Uncategorized';
if (!grouped[category]) {
grouped[category] = [];
}
grouped[category].push(doc);
});
return grouped;
}
5. Update Individual Doc Pages
Current state: Already renders markdown with back link
Changes needed:
- Parse frontmatter when rendering doc
- Use frontmatter
titleinstead of filename - Show metadata below title (category, repo, date)
- Update back link to "← Back to Library" instead of "← Back to all docs"
Example:
┌─────────────────────────────────────┐
│ ← Back to Library │
│ │
│ Learning Feed Idea │
│ Meta • yap • Nov 4, 2025 │
│ ───────────────────────────────── │
│ [rendered markdown content] │
└─────────────────────────────────────┘
6. Styling - Spotify-Inspired Dark Theme
Color palette (use these consistently):
- Background:
#121212(main),#181818(elevated surfaces) - Card background:
#282828 - Text primary:
#ffffff - Text secondary:
#b3b3b3 - Accent:
#1db954(Spotify green) or keep current blue#4a9eff - Border/divider:
#404040
Typography:
- Keep existing font stack
- Title: Bold, larger size
- Metadata: Smaller, secondary color
Cards:
.doc-card {
background: #282828;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
transition: background 0.2s;
cursor: pointer;
}
.doc-card:hover {
background: #3e3e3e;
}
Light mode: Keep existing light mode support with @media (prefers-color-scheme: light)
7. Category Icons
Use emoji icons for each category:
- Personal: 💭
- System: 🔧
- Stories: 📖
- Design: ⚙️
- Meta: 💡
- Setup: 📄
8. Navigation Flow
/ → Homepage (Recently Added, top 10)
Click "Library" → /library
Click doc card → /:filename
/library → All docs organized by category
Click "Home" → /
Click doc → /:filename
/:filename → Individual doc page
Click "Back to Library" → /library
Technical Requirements
- No breaking changes: Keep all existing routes working
- PWA compatibility: Don't break manifest, service worker, icons
- Mobile responsive: Should work on phone/tablet
- Performance: Parsing 27 files on each request is fine for now (can optimize later)
- Error handling: If frontmatter missing, gracefully fall back to filename-based title
Testing Checklist
After implementation, verify:
- All 27 markdown files have frontmatter
- Homepage shows 10 most recent docs
- Library page shows all docs grouped by category
- Clicking docs navigates correctly
- Back navigation works from doc pages
- Dark mode still works
- Light mode still works (if user prefers)
- Service worker still registers (check browser console)
- No console errors
- Responsive on mobile viewport
- Can run smoke tests (
./smoke-test.sh) without errors - Server restarts cleanly with systemd
Commands to Run
# Install new dependency
npm install gray-matter
# Restart server after changes
sudo systemctl restart blog
# Check server status
sudo systemctl status blog
# View logs if issues
sudo journalctl -u blog -n 50
# Test endpoints
curl http://localhost:3000/
curl http://localhost:3000/library
curl http://localhost:3000/README.md
Files to Modify
server.js- Add frontmatter parsing, new routes, updated HTML templates- All 27
.mdfiles - Add frontmatter to top of each package.json- Add gray-matter dependency
Files NOT to Touch
manifest.jsonsw.jspublic/icon.svg.gitignoresmoke-test.shbrowser-test.js- Any systemd service files
Expected Outcome
A Spotify-like documentation browser where:
- Homepage feels like "Your Library" with recent activity
- Library page shows all content organized by category
- Clean, dark interface matching Spotify's aesthetic
- All existing functionality preserved (PWA, dark mode, logging, etc.)
- Easy to browse and discover content
Notes for Implementation
- Keep the existing footer ("Built to stay focused. Living the system.")
- Maintain service worker registration script on all pages
- Preserve manifest link in
<head> - Keep existing logging middleware
- Use existing CSS approach (inline
<style>tags) - Don't worry about "moving docs between categories" UI yet - that's future work
- Focus on browsing experience first
Example Frontmatter for Reference
---
title: "Learning Feed - Making Documentation as Addictive as Social Media"
category: "Meta"
repo: "yap"
dateAdded: "2025-11-04"
tags: ["product-ideas", "learning", "attention-design"]
---
Good luck! Build something that makes browsing these docs feel as smooth as scrolling through Spotify playlists.