Introduction
grdn (styled as grdn or "the garden") is my personal digital garden—a publishing platform for random musings, bad prose, and everything in between. It's a space that blurs the line between a blog and a living, breathing ecosystem.
The name comes from my broader "prjctimg" branding, which started as a creative outlet and evolved into something more. The garden metaphor felt right: posts grow over time, some bloom immediately, others are seeds waiting for the right moment.
This devlog covers the architecture, features, and the more interesting technical decisions that make grdn what it is.
The Content System
Posts live as Markdown files in data/blog/garden/. Each file has YAML frontmatter that controls how it appears:
yaml
Post Layouts
The system supports four distinct layouts, giving each post a different reading experience:
The layout is rendered dynamically via PostLayouts.tsx, which selects the appropriate component based on the frontmatter.
Tags and Organization
Tags are first-class citizens. Every tag gets its own auto-generated page at /tags/[tag]/, showing all posts with that tag. The tag cloud on the home page makes discovery easy.
Reading List
Books I'm currently reading are stored in data/reading.yml:
yaml
This appears on the home page as a widget, complete with reading progress.
The Ambient Engine
This is arguably the most unique feature: a procedural nature sounds engine built with Tone.js. Instead of playing audio files, it synthesizes animal sounds in real-time.
Supported Species
The engine produces sounds for:
- Day birds: nightingale, koel, shama, white-eye, eagle
- Night creatures: frog, owl, wolf, hyena
- Ocean: seagull, whale
Each sound is generated using oscillators with specific waveforms, frequencies, and envelope patterns unique to that animal.
Dynamic Mixing
The soundscape changes based on two factors:
- Time of day: Day mode plays birds; night mode switches to owls, wolves, and hyenas
- Scroll position: Scrolling toward the bottom fades in ocean sounds (seagulls, whales)
This creates an immersive, contextual audio experience without requiring any audio files.
Visual Design
Seasonal Backgrounds
The garden wouldn't feel alive without environmental visuals. The SeasonalBackground component renders a Canvas-based particle system that changes with Southern Hemisphere seasons:
- Spring: Pink/green particles (flowers, pollen)
- Summer: Bright green/yellow (lush foliage)
- Autumn: Orange/red/brown (falling leaves)
- Winter: White/blue (snow)
The particle count, velocity, and color are all configured per-season in the component.
Zen Graphics
Every post gets a unique abstract visual generated via ZenGraphic.tsx. The trick: it uses the post's title as a seed for a deterministic random number generator. This means the same title always produces the same graphic, but different titles create unique compositions.
The graphics use:
- Circle, line, and polygon shapes
- Randomized sizes, positions, and opacities
- Pulsing CSS animations with staggered delays
- Theme-aware colors (different palette for light vs dark mode)
Theming System
The garden supports six themes, all powered by CSS custom properties:
The ThemeContext manages theme state across the app, with system preference detection on first load and manual override persistence.
Smart Features
Scheduled Post Countdown
Posts can have a due date in frontmatter. The NextDropCountdown component displays a live countdown, and when the due date passes, the post automatically reveals itself.
The reveal state is persisted in localStorage, so users won't see the countdown again after a post is revealed.
Weather Widget
Real-time weather data comes from the Open-Meteo API (free, no key required). The location is hardcoded to Harare, Zimbabwe—home of the garden's author.
Text-to-Speech
Every post includes a built-in TTS button that uses the browser's native Speech Synthesis API. Users can listen to articles being read aloud without external dependencies.
Search
Pressing Ctrl+K opens a full-text search modal. It indexes post titles, tags, and content in real-time. Keyboard navigation (arrow keys + Enter) makes it fully accessible without a mouse.
Architecture
Tech Stack
- Framework: Next.js 16 (App Router)
- Runtime: Bun
- Styling: Tailwind CSS + CSS variables
- State: React Context API
- Audio: Tone.js
- Language: TypeScript
Data Layer
Posts are read from the filesystem at build/request time. The lib/data.ts module handles:
- Markdown parsing (with frontmatter extraction)
- Post filtering (drafts, scheduled posts)
- Sorting (date, alphabetical)
- Tag aggregation
- Caching (in-memory)
Closing Thoughts
The garden is an experiment in blending a personal blog with ambient interactivity. Most blogs are static; this one breathes. The seasonal backgrounds shift, the soundscape changes with time and scroll position, and posts can be planted for future discovery.
It's not perfect—there's always more to add (reading time estimates, better mobile support, more themes). But that's the point: a garden is never finished, it just grows.