The Projects page (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/witch-dev/llms.txt
Use this file to discover all available pages before exploring further.
be component) — themed as the Grimoire of Builds — displays a horizontally scrollable row of circular project cards. A tag filter bar above the carousel lets visitors narrow the visible cards by technology. All filtering happens client-side with no network requests.
Project Data
Projects are defined in thev array. Each object describes one card:
Circular Card Design
Each project is rendered as a circular glass panel (aspect-square, rounded-full) with a full-bleed background image.
Idle state
- The background image is rendered with
mix-blend-mode: luminosity, desaturating it into a dark, atmospheric silhouette. - No text is visible; only the image and, when applicable, the mocked-data badge (see below).
Hover state
On pointer hover, the card transitions to its active state:- The image blend mode shifts to
normal, restoring full colour. - A semi-transparent dark overlay fades in over the image.
- Three elements appear from the overlay:
- Project title — bold, centred
- Project description — smaller text beneath the title
- Three action buttons displayed in a row:
| Button | Purpose |
|---|---|
| Open.exe | Opens the live demo (or mocked preview) |
| Source Spell | Links to the project’s source code repository |
| Read Incantation | Opens a detailed case study or README |
duration-300 ease-in-out to keep the reveal smooth.
Mocked Data Badge
When a project’smocked field is true, a TriangleAlert icon badge is pinned to the card edge with the tooltip / label “Demo uses mocked data”. This badge is rendered at all times (not just on hover) so visitors are never surprised by placeholder content in a live demo.
Tag Filtering
A filter bar above the carousel contains:- An “All Spells” reset button (always visible, clears the active filter)
- One pill per unique tag drawn from every project’s
tagsarray
React · Node.js · PostgreSQL · Next.js · Socket.io · Tailwind · Vue · Weather API · CSS Grid · React Native · Firebase · Crypto
How filtering works
- The active filter tag is stored in local component state (e.g.
activeTag). - When a pill is clicked,
activeTagis set to that tag’s string. - The carousel renders only cards whose
tagsarray includesactiveTag. - Clicking “All Spells” resets
activeTagtonull, showing every card.
Tags are matched with a simple
Array.prototype.includes check, so tag strings are case-sensitive. Ensure new project tags use exactly the same casing as the pills (e.g. "React", not "react").Scroll Behavior
The carousel container is configured for a smooth, snapping horizontal scroll experience:| CSS utility | Effect |
|---|---|
overflow-x-auto | Enables horizontal scrolling |
no-scrollbar | Hides the native scrollbar for a cleaner look |
snap-x snap-mandatory | Snaps each card into the viewport on scroll |
cursor-grab | Signals that the carousel can be click-dragged |
Adding a New Project
Append a new object to thev array. All five fields are required: