Skip to main content

Documentation Index

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

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

The Blog page presents articles as a stack of vintage postcards resting on a wooden shelf. Postcards sit layered on top of one another in a fixed-height container; clicking any card fans it out and expands it to display its full excerpt. Clicking the same card again collapses it back into the stack. A wood-panelled shelf is rendered below the card stack using absolutely-positioned decorative divs, and an “Archives” label on the shelf front ties the whole assemblage together.
Route: /blog
Static HTML: pages/Blog.html
Page function: G() in assets/main.js
Data array: F in assets/main.js

What the page displays

ElementContent
Section heading (h1)Tales from the Crypt
SubtitleVintage postcards detailing my descent into madness.
Card stack containerrelative w-full max-w-md h-[300px] mt-20
Primary componentPostcard stack — one per article
Shelf decorationTwo wood-coloured div layers (#3e2723 / #4e342e) with an “Archives” label

Articles data

Four articles are stored in the F array in assets/main.js.
IDTitleDateBackground colour
1Tales from the DOMOct 31, 2023#f4f1ea (cream)
2The Haunted HookOct 15, 2023#e2d5c4 (tan)
3CSS Grid GraveyardSep 28, 2023#d7ccc8 (grey-rose)
4Vampire VariablesSep 10, 2023#cfd8dc (slate-blue)

Article excerpts

Tales from the DOM (Oct 31, 2023): “Dearest reader, I encountered a terrifying bug today. The elements were shifting without cause. It was… a race condition.”
The Haunted Hook (Oct 15, 2023):useEffect ran infinitely. The browser screamed. Memory spiked. I had forgotten the dependency array. May the code gods have mercy.”
CSS Grid Graveyard (Sep 28, 2023): “Buried my floats today. Grid is the future. The layout is finally at peace, resting perfectly centered in its container.”
Vampire Variables (Sep 10, 2023): “Global variables are draining the life from this application. We must isolate them before they infect the entire state.”

Raw data structure

// assets/main.js — array F
const F = [
  {
    id: 1,
    title: "Tales from the DOM",
    date: "Oct 31, 2023",
    excerpt: "Dearest reader, I encountered a terrifying bug today. The elements were shifting without cause. It was... a race condition.",
    color: "#f4f1ea",
  },
  {
    id: 2,
    title: "The Haunted Hook",
    date: "Oct 15, 2023",
    excerpt: "useEffect ran infinitely. The browser screamed. Memory spiked. I had forgotten the dependency array. May the code gods have mercy.",
    color: "#e2d5c4",
  },
  {
    id: 3,
    title: "CSS Grid Graveyard",
    date: "Sep 28, 2023",
    excerpt: "Buried my floats today. Grid is the future. The layout is finally at peace, resting perfectly centered in its container.",
    color: "#d7ccc8",
  },
  {
    id: 4,
    title: "Vampire Variables",
    date: "Sep 10, 2023",
    excerpt: "Global variables are draining the life from this application. We must isolate them before they infect the entire state.",
    color: "#cfd8dc",
  },
];

Halloween-themed concept

Articles are recast as letters from a doomed correspondent — the vintage postcard format implies secrecy, age, and drama. The wooden shelf anchors the cards in a physical space, evoking an old crypt or haunted library storeroom. Each article title (“Haunted Hook”, “Crypt”, “Vampire Variables”) wraps real frontend developer pain-points in horror-story language, making the blog feel in-character without sacrificing the actual technical content.

Interactive behaviour

The page component G() manages a single piece of React state: selectedId.
const [selectedId, setSelectedId] = React.useState(null);
  • When a Postcard is clicked, onClick is called with its id.
  • If selectedId already equals that id, it is set back to null (collapse).
  • Otherwise selectedId is set to the clicked id (expand).
  • Each Postcard receives an isSelected prop (selectedId === article.id) so it knows whether to show its expanded state.
Only one postcard can be expanded at a time — clicking a second card while one is open implicitly collapses the first (because selectedId can only hold one value).

Shelf decoration

The shelf is built from three absolutely-positioned layers inside the relative container:
LayerBackgroundPositionPurpose
Top shelf plank#3e2723bottom: -20px, z-0Shelf surface behind cards
Bottom shelf body#4e342ebottom: -40px, z-50Shelf front face
”Archives” badge#2d1b18Centred on front faceDecorative label

Framer Motion animations

The header block uses the standard top-drop entrance. Individual Postcard components manage their own expand/collapse animations internally (the isSelected prop drives them).
// Header motion.div
{
  initial: { y: -20, opacity: 0 },
  animate: { y: 0,   opacity: 1 }
}

How to customise

1

Add a new article

Append an object to the F array with a unique id, title, date, excerpt, and color. Choose a muted background color (hex) so the postcard looks aged and thematic.
2

Edit an existing article

Find the object by id in the F array and update title, date, or excerpt as needed.
3

Change a postcard colour

Update the color field on the relevant object. Muted, desaturated tones (#f0e8d8, #d4c5b0) work best to maintain the vintage-postcard look.
4

Reorder articles

Move objects within the F array. The stack renders cards in array order, with later cards visually on top.
Because the Postcard component handles its own expanded animation internally via isSelected, you can link each article to a full blog post page by adding a url field to the data object and passing it as a prop — no changes to the page-level G() function required.

Build docs developers (and LLMs) love