Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/y2k-web/llms.txt

Use this file to discover all available pages before exploring further.

The Blog page — titled “Web Log” in the UI — is a love letter to early-2000s personal blogging culture. Its design is directly inspired by LiveJournal and similar platforms of the era: each post entry includes not just a title and date, but also a mood field (complete with a tiny emoji) and a music field showing what the author was listening to when they wrote it. The page header mimics the banded, pastel aesthetics of classic blog skins, and post excerpts are rendered in serif or pixel fonts for maximum authenticity.

Blog Post Data Structure

Posts are stored as an array of objects at the top of the Blog component. Each object has the following shape:
FieldTypeDescription
idnumberUnique identifier used as the React list key
titlestringPost headline displayed in the entry header
datestringHuman-readable date string (e.g. "May 28, 2026 @ 11:45 PM")
moodstringCurrent mood label shown below the date
musicstring”Currently playing” track shown below the mood
contentstringFull post body text displayed inside the modal
The three built-in demo posts are:
const posts = [
  {
    id: 1,
    title: 'Why I still use tables for layout (sometimes)',
    date: 'May 28, 2026 @ 11:45 PM',
    mood: 'nostalgic',
    music: 'Darude - Sandstorm',
    content: 'Look, I know Flexbox and Grid are great...',
  },
  {
    id: 2,
    title: 'Just bought a new mechanical keyboard',
    date: 'May 20, 2026 @ 02:15 AM',
    mood: 'excited',
    music: 'Linkin Park - In The End',
    content: 'Cherry MX Blues. My coworkers are going to hate me...',
  },
  {
    id: 3,
    title: 'CSS Variables are magic',
    date: 'May 10, 2026 @ 09:00 AM',
    mood: 'enlightened',
    music: 'Eiffel 65 - Blue',
    content: 'I finally refactored my entire site to use CSS variables...',
  },
];

Post List Rendering

Each post is mapped to a summary card that shows the title, date, mood, and music fields alongside a truncated excerpt and a “Read More” button. The “Read More” button sets selectedPost in component state, which triggers the modal to open:
{posts.map((post) => (
  <div key={post.id} className="blog-entry">
    <h2 className="post-title">{post.title}</h2>
    <div className="post-meta">
      <span>📅 {post.date}</span>
      <span>😌 Mood: {post.mood}</span>
      <span>🎵 Music: {post.music}</span>
    </div>
    <p className="post-excerpt">{post.content.slice(0, 120)}...</p>
    <button onClick={() => setSelectedPost(post)}>Read More »</button>
  </div>
))}

Full-Post Modal with Framer Motion

Clicking “Read More” stores the selected post object in local state. AnimatePresence from Framer Motion watches for the presence of selectedPost and animates the modal WindowFrame in and out with a scale + opacity transition:
const [selectedPost, setSelectedPost] = useState(null);
// ...
<AnimatePresence>
  {selectedPost && (
    <motion.div
      initial={{ scale: 0.8, opacity: 0 }}
      animate={{ scale: 1, opacity: 1 }}
      exit={{ scale: 0.8, opacity: 0 }}
    >
      <WindowFrame title={`Viewing Post: ${selectedPost.title}`}>
        {/* full post content */}
      </WindowFrame>
    </motion.div>
  )}
</AnimatePresence>
The modal is dismissed by clicking a close button which calls setSelectedPost(null). Setting state to null causes AnimatePresence to detect the child’s removal and play the exit animation before unmounting.

Route Registration

The Blog component (Vp in the compiled bundle) is mounted at /blog:
// Inside <Routes>:
<Route path="/blog" element={<Blog />} />
To add a new blog post, append an object to the posts array following the structure above. Give it the next sequential id, fill in the title, date, mood, music, and content fields, then save — the new entry will appear automatically. To sort newest-first, add a .sort() call after the array declaration:
const sortedPosts = [...posts].sort((a, b) => b.id - a.id);
Then map over sortedPosts instead of posts in the render.

Build docs developers (and LLMs) love