👻 Ghost Stories - Kiroween Hackathon Entry

"Stories that haunt your WordPress site... then vanish into the night"

Inspiration

Every Halloween (and Thanksgiving, Christmas, etc), stories are told around campfires—ephemeral tales that captivate, then fade into memory. We wanted to bring that same magic to the web.

Instagram Stories revolutionized how we share moments, but WordPress—powering 43% of the web—has been left in the dark ages.

Before becoming a Python backend developer I started my career developing WP websites in Ecuador, 8 years ago. A relative of mine contacted me a few months ago wanting stories in his site, I searched for a plugin and I found only abandoned, unmaintained, bloated and expensive plugins. I found one that was somewhat functional, and using Kiro I resurrected it :)

The "ghost" theme runs deep:

  • Stories appear on your site, captivate visitors, then vanish after their expiration time
  • Zero external dependencies—the plugin leaves no trace on third-party servers
  • Built to be invisible to performance metrics—conditional loading means zero impact on pages without stories

Kiro became my supernatural companion in this journey, helping me completely resurrect the old plugin I found, delete all dependencies and make a lean plugin that does 1 thing very well.

What it does

Ghost Stories is a WordPress plugin that brings Instagram-style ephemeral stories to any WordPress website.

Core Features:

🔮 Story Creation - Upload images and videos through the familiar WordPress admin. Drag-and-drop to reorder. Set expiration times from 1 hour to 7 days.

Auto-Expiration System - Stories automatically "ghost" themselves after their time is up, moving to draft status. The cleanup runs via WordPress cron—no external services needed.

📱 Mobile-First Modal Viewer - Full-screen, immersive story experience with:

  • Touch gestures (swipe horizontal for media, vertical for stories)
  • Tap navigation zones
  • Keyboard support (arrow keys, Escape)
  • Progress bars synchronized with media duration
  • Video controls with persistent mute state

🧱 Gutenberg Block - Drop stories anywhere using the native block editor. Select which stories to display, set alignment, done.

🔌 REST API - Full API for headless WordPress setups:

  • GET /wp-stories/v1/stories - Fetch active stories
  • GET /wp-stories/v1/stories/{id} - Get specific story with media
  • POST /wp-stories/v1/stories/{id}/view - Track views (CSRF protected)

Performance Optimized:

  • Conditional asset loading (no stories = no scripts loaded)
  • Transient caching for expiration checks
  • Lazy loading for images
  • Cache headers on API responses

🔒 Security First:

  • Nonce verification on all forms
  • Capability checks for admin operations
  • Input sanitization and output escaping
  • No external API calls or tracking

How we built it

This is where Kiro truly shined. We used nearly every Kiro feature available:

Specs for Structure

We started by creating a full specification in .kiro/specs/plugin-modernization/:

  • requirements.md - 12 requirement categories with acceptance criteria
  • design.md - Architecture diagrams, component interfaces, data models
  • tasks.md - Implementation plan broken into 9 phases, 50+ subtasks

Kiro helped us think through edge cases we would have missed—like what happens when a story expires mid-viewing, or how to handle video progress synchronization.

Steering for Consistency

We set up steering rules in .kiro/steering/:

  • product.md - Product overview and target audience
  • structure.md - File organization and naming conventions
  • tech.md - Technical stack and common commands

This meant every time we asked Kiro for help, it understood our WordPress context, our class naming patterns (Story_* prefix), and our testing approach (PHPUnit + Brain Monkey).

Chat for Rapid Development

The conversational flow was incredible for:

  • Debugging the modal viewer's touch gesture conflicts
  • Implementing the video progress bar synchronization
  • Refactoring the entire codebase from "Mega Stories" to "Ghost Stories" (Kiro updated 15+ files in one session!)

Tech Stack

  • PHP 7.4+ - OOP architecture with singleton pattern for main plugin class
  • Vanilla JavaScript - No build process, ES5-compatible for maximum WordPress compatibility
  • WordPress APIs - Custom Post Types, REST API, Settings API, Block API
  • PHPUnit 9.6 - Unit tests with Brain Monkey for WordPress mocking

Challenges we ran into

The Modal Visibility Nightmare

Our modal would open but remain invisible. After hours of debugging, we discovered a CSS specificity war between our styles and the theme. Kiro helped us implement !important overrides strategically and add inline style fallbacks.

Video Progress Synchronization

Getting the progress bar to smoothly sync with video playback was tricky. The timeupdate event fires inconsistently across browsers. We ended up using requestAnimationFrame for smooth 60fps updates, with Kiro helping us implement proper cleanup to prevent memory leaks.

Touch Gesture Conflicts

Horizontal swipes for media navigation kept conflicting with vertical swipes for story navigation. Kiro helped us implement angle-based detection—calculating the swipe angle and only triggering the appropriate action when the angle clearly indicates horizontal (< 45°) or vertical (> 45°) intent.

The Great Renaming

Midway through, we decided to rename from "Mega Stories" to "Ghost Stories" for the hackathon theme. This meant updating:

  • Constants (MEGA_STORIES_*GHOST_STORIES_*)
  • Functions (mega_stories_*ghost_stories_*)
  • Options, text domains, console logs, API headers...

Kiro handled this massive refactor across 15+ files in a single session, catching references we would have missed manually.

Accomplishments that we're proud of

I don't know PHP anymore, I really vibe coded this plugin with the few concepts I remember from WordPress. I also don't know that much Frontend, specially vanilla JavaScript but was still able to deliver a functional plugin/

Zero Dependencies - No Composer packages required for production. No external APIs. No tracking. Just WordPress.

Full Spec-Driven Development - We have comprehensive requirements, design docs, and task lists. This isn't a hackathon hack—it's a maintainable, extensible plugin.

Native WordPress Integration - Uses Custom Post Types, REST API, Block API, Settings API, Transients API. Feels like it belongs in WordPress core.

Mobile-First UX - The modal viewer rivals native mobile apps with smooth gestures, progress indicators, and video controls.

Performance Conscious - Conditional loading means zero performance impact on pages without stories. Caching throughout.

What we learned

Kiro Specs Are Game-Changing

Writing requirements and design docs before coding felt slow at first, but paid massive dividends. When we hit implementation, we knew exactly what to build. Edge cases were already considered. The architecture was solid.

Steering Rules Save Context

Instead of re-explaining our tech stack every conversation, steering rules kept Kiro informed. It knew we were building a WordPress plugin, using PHPUnit, following specific naming conventions.

AI Pair Programming Works

Kiro wasn't just autocomplete—it was a thinking partner. It caught bugs we missed, suggested better approaches, and handled tedious refactoring that would have taken hours manually.

WordPress Is Still Relevant

Building for WordPress in 2024 might seem old-school, but 43% of the web runs on it. There's massive value in bringing modern UX patterns (like Stories) to this platform.

What's next for Ghost stories

Immediate Roadmap

  • [ ] WordPress.org submission for the plugin directory
  • [ ] User-facing settings page (currently uses sensible defaults)
  • [ ] Story analytics dashboard
  • [ ] Shortcode support for non-Gutenberg users

Future Haunts

  • [ ] Story highlights (permanent collections)
  • [ ] User-submitted stories (frontend submission)
  • [ ] Story reactions and polls

Built With

Share this project:

Updates