Back to all docs

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:

Current State

Location: /home/ubuntu/yap/

Key files:

Current behavior:

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:

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:

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:

CSS styling:

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:

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:

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):

Typography:

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:

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

  1. No breaking changes: Keep all existing routes working
  2. PWA compatibility: Don't break manifest, service worker, icons
  3. Mobile responsive: Should work on phone/tablet
  4. Performance: Parsing 27 files on each request is fine for now (can optimize later)
  5. Error handling: If frontmatter missing, gracefully fall back to filename-based title

Testing Checklist

After implementation, verify:

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

  1. server.js - Add frontmatter parsing, new routes, updated HTML templates
  2. All 27 .md files - Add frontmatter to top of each
  3. package.json - Add gray-matter dependency

Files NOT to Touch

Expected Outcome

A Spotify-like documentation browser where:

Notes for Implementation

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.