Under the Hood
How this website is built, one detail at a time.
Welcome to the control room. This page documents how hvpandya.com is built, maintained, and constantly tinkered with. Whether you’re a curious visitor or a fellow builder looking for inspiration, I hope you find something useful here.
The Philosophy
This isn’t a template. It’s not a WordPress theme or a Squarespace site. Every pixel, every interaction, every micro-animation has been deliberately crafted. The site is designed to feel warm and personal, like you’re reading someone’s carefully maintained notebook rather than consuming content on a generic blog platform.
Writing online since 2008 — this site has evolved through Blogspot, WordPress, Squarespace, and now a fully bespoke build. The current incarnation prioritizes craft, performance, and personality over convenience.
Tech Stack
| Layer | Technology | Why |
|---|---|---|
| Static Site Generator | Jekyll (Ruby) | Fast, mature, great for content-heavy sites |
| Hosting | Netlify | Auto-deploys from Git, great CDN, serverless functions |
| Database | Supabase | PostgreSQL for reaction counts, simple REST API |
| Fonts | Self-hosted (Ivar, Departure Mono) | No Google Fonts, full control over loading |
Performance optimizations implemented to keep things snappy:
- Font preloading with correct WOFF2 formats
- Deferred JavaScript loading
- Excluded 48 unused font files to reduce bundle from 74MB to 3MB
Typography System
Three carefully chosen typefaces create the site’s voice:
Ivar Text — The Storyteller
A contemporary serif for body text. It’s readable, warm, and has that editorial quality that makes long-form reading a pleasure.
Ivar Headline — The Announcer
Bold and confident for titles. Pairs naturally with its text sibling.
Departure Mono — The Technical Voice
A monospace font with personality. Used for:
- UI elements (lozenges, buttons, labels)
- Code snippets and technical content
- Navigation items
There’s also JetBrains Mono specifically for code blocks — the distinction matters. Departure Mono is for user-written content (prompts, inputs), while JetBrains Mono is for system output (terminal responses, code examples).
The Color Palette
The color system is inspired by traditional Japanese aesthetics — muted, sophisticated, and harmonious:
| Name | Hex | Usage |
|---|---|---|
| Matcha | #4a6848 |
Design topics |
| Indigo | #2d4a6f |
Leadership topics |
| Amber | #8a6830 |
Career topics |
| Vermillion | #9a4a3a |
Product topics |
| Wisteria | #6a5878 |
Observations |
| Sakura | #96525e |
AI experiments |
| Madder | #7a4a48 |
Life topics |
| Coral | #d4826a |
Special accents |
The rule: Never define colors on-the-fly. Every color lives as a CSS variable in the palette, documented and intentional.
Interactive Features
The Emoji Reaction Bar
Every article has a reaction bar with five carefully chosen options:
- 🤔 Very thoughtful — for pieces that make you think
- 🙏 So relatable — when it resonates personally
- 👍 So good — general appreciation
- ❤️ Loved it — strong emotional response
- 🤯 Blew my mind — for the surprising insights
The Crown Feature: The emoji with the highest count gets a 👑 crown. When the leader changes, an 8-bit victory sound plays and a celebratory tooltip appears with messages like “New leader!” or “Taking the crown!”
Technical details:
- Reactions persist via Netlify Functions → Supabase
- Atomic increments prevent race conditions
- Flying emoji animations use Web Animation API (not CSS keyframes) for cross-browser reliability
- Haptic feedback on mobile devices
- Explosion effect triggers after 8-10 rapid clicks
The Notes Page
The /notes page isn’t just a list — it’s a curated browsing experience:
- Topic lozenges: Color-coded pills that categorize each post
- Reaction counts: Show total reactions with a ⚡️ prefix
- Viral tier: Top 10% most-reacted posts get gold styling
- Contextual tooltips: Hover over counts to see messages like “A crowd favorite” or “This one took off”
The tooltips are dynamically generated based on percentile rankings across all posts — bottom 25% get “Undiscovered gem” type messages, top 25% get “This one took off” celebratory ones.
The AMA Page
The /ama page features:
- Floating speech bubble: Cycles through friendly messages with smooth color transitions
- Anonymous question submission: No email required, questions go to a Supabase inbox
- Answered Q&A cards: Stored in version control (not database), with topic tags and like counts
- Validation tooltips: Try submitting with an empty field — you’ll get a friendly nudge like “Forgot something?”
The Lightbox
A custom-built lightbox with accessibility baked in:
- Focus trap: Tab key stays within the lightbox when open
- Keyboard navigation: Escape to close, Enter/Space to open
- Alt text propagation: Screen readers get the original image description
- Smooth animations: No jarring transitions
Accessibility
This site is built to WCAG 2.1 AA standards:
Focus Indicators
Every interactive element has a visible focus ring (2px blue outline) that only appears for keyboard users. Mouse clicks don’t show the ring — this uses the :focus-visible selector.
Keyboard Navigation
- Skip link: Homepage has a “Skip to main content” link for screen reader users
- Emoji reactions: Full keyboard support — tab to navigate, Enter/Space to react
- Lightbox: Opens with Enter, closes with Escape, focus returns to trigger image
Screen Reader Support
- Semantic HTML throughout
- ARIA labels on interactive elements
- Live regions announce reaction count changes
Performance Optimizations
Font Loading
Fonts are preloaded with correct MIME types:
<link rel="preload" href="/assets/fonts/ivar-text/IvarText-Regular.woff2"
as="font" type="font/woff2" crossorigin>
JavaScript Strategy
All scripts use defer to prevent render blocking. Critical interactions (like the reaction bar) work without JavaScript — they just won’t persist.
Bundle Size
By excluding unused font weights and formats in the Jekyll config, the fonts folder went from 74MB to 3MB.
Animation Philosophy
Animations serve a purpose:
- Flying emojis: Provide satisfying feedback when reacting
- Loading dots: Indicate data fetching without jarring spinners
- Crown sound: Creates a moment of delight when leadership changes
- Tooltip transitions: Smooth 300ms fades, never instant
Nothing moves just to move. Every animation earns its place.
The Build Process
# Local development
bundle exec jekyll serve
# Production build
JEKYLL_ENV=production bundle exec jekyll build
Netlify watches the master branch and auto-deploys on every push. Build time is typically under 30 seconds.
Directory Structure
├── _posts/ # Blog posts (Markdown)
├── _drafts/ # Draft posts (not published)
├── _layouts/ # Jekyll layouts
│ ├── default.html # Main layout
│ ├── default-homepage.html # Homepage layout
│ ├── post.html # Blog post layout
│ └── page.html # Static page layout
├── _includes/ # Reusable HTML partials
├── assets/
│ ├── css/ # Component stylesheets
│ ├── js/ # JavaScript files
│ └── fonts/ # Self-hosted fonts
├── netlify/functions/ # Serverless functions
├── styles.css # Main stylesheet (~68KB)
└── *.md # Static pages
What’s Next?
This site is never “done.” Current experiments include:
- More interactive essays with Rough Notation annotations
- Improved mobile typography
- Dark mode (maybe)
If you’re building your own site and have questions, feel free to reach out via the AMA page or on Twitter.
Built with care, iterated with love.