DEV Community

Cover image for # Building Blood Stream: How Kiro AI Helped Me Create a Horror Streaming Platform in 21 Days
Akachukwu Onyekesi
Akachukwu Onyekesi

Posted on

# Building Blood Stream: How Kiro AI Helped Me Create a Horror Streaming Platform in 21 Days

Building Blood Stream: How Kiro AI Helped Me Create a Horror Streaming Platform in 21 Days

Here's how I used Kiro's spec-driven development, agent hooks, and steering docs to build something that would've taken months manually.


The Problem: Horror Streaming is Boring

Every streaming app looks the same. Netflix, Hulu, Disney+โ€”black backgrounds, white text, rectangular thumbnails. For most content, that's fine.

But horror? Horror fans are fanatics. They attend midnight screenings in costume. They visit haunted attractions. They collect memorabilia. They deserve an experience that matches their passion.

So I asked: What if the streaming app itself was part of the horror experience?


The Solution: Blood Stream

Blood Stream is a horror movie streaming platform where:

  • Movie posters drip blood when you hover over them
  • Search uses a Ouija board interface
  • Your watchlist is a morgue with sliding body drawers
  • Video players have blood-filled progress bars
  • Atmospheric fog, Gothic typography, and eerie sound design create genuine immersion

Built in 21 days for the Kiroween hackathon using Kiro AI, it won $27,500 in prizes and received acquisition offers.

Here's exactly how I used Kiro to make it happen.


Why Kiro AI Changed Everything

Most developers think AI coding is about clever prompting. Wrong.

The secret is using the right Kiro feature for each task:

  • ๐Ÿ“‹ Specs for complex logic
  • ๐Ÿค– Agent hooks for automation
  • ๐ŸŽฏ Steering docs for consistency
  • ๐Ÿ’ฌ Vibe coding for creative polish

Let me break down each one.


Part 1: Spec-Driven Development

The Old Way (Without Specs)

Me: "Make a blood-dripping effect"

Kiro: generates basic animation

Me: "No, make it fall with gravity"

Kiro: updates animation

Me: "Add a splatter at the bottom"

Kiro: adds splatter

Me: "Make it look more realistic"

Kiro: tries again

Me: "Still not quite right..."

Result: 6 iterations, 2 hours, mediocre outcome

The New Way (With Specs)

I wrote a precise specification:

## Blood Drip Animation Specification

**Trigger:** Mouse hover over movie poster

**Behavior:**
WHEN user hovers over poster,
THE Theme_Engine SHALL:
1. Spawn blood droplet at random X position along top edge
2. Animate droplet falling with these properties:
   - Initial velocity: 0
   - Acceleration: 980 pixels/sยฒ (gravity)
   - Shape: Teardrop (elongates during fall)
   - Duration: 1.2 seconds
   - Easing: ease-in
3. At bottom impact:
   - Spawn 10-20 particles in radial pattern
   - Particle velocity: Random 50-150 pixels/s
   - Particle lifetime: 0.5 seconds
   - Particle fade: Linear opacity 1โ†’0

**Performance:**
- Must maintain 60 FPS
- Use transform (not position) for GPU acceleration
- Respect prefers-reduced-motion

**Accessibility:**
- No animation if prefers-reduced-motion is set
- Does not interfere with poster clickability
Enter fullscreen mode Exit fullscreen mode

Kiro's output: Perfect code, first try, 10 minutes.

The Difference

Without specs: Ambiguous requirements โ†’ multiple iterations โ†’ frustration

With specs: Precise requirements โ†’ exact implementation โ†’ ship it

I created 25 specifications like this for Blood Stream. Each one eliminated ambiguity and gave Kiro testable acceptance criteria.

Files in /.kiro/specs/:

  • blood-effects.spec.md - All blood animations
  • ouija-search.spec.md - Ouija board interface
  • morgue-watchlist.spec.md - Watchlist functionality
  • video-player.spec.md - Player controls
  • performance.spec.md - Speed and FPS targets

Part 2: Agent Hooks (Automation That Saves Hours)

Agent hooks are Kiro's superpower for automation. I created four hooks that ran automatically during development:

1. Image Optimization Hook

Problem: TMDb API returns high-resolution posters (5MB+ each). Loading 20 posters = 100MB of data.

Solution: Hook automatically:

  • Compresses JPEGs to 80% quality
  • Converts to WebP with JPEG fallback
  • Generates responsive srcsets (w300, w500, original)
  • Caches optimized versions

Impact: Image load time reduced by 60%. Saved ~4 hours of manual optimization.

2. Performance Testing Hook

Problem: Animations look great but might tank performance.

Solution: Hook runs Lighthouse on every build and:

  • Fails build if performance score drops below 85
  • Alerts if animations drop below 50 FPS
  • Generates performance reports in /.kiro/reports/

Impact: Caught 3 performance regressions before they reached production. No more manual Lighthouse testing.

3. Theme Consistency Hook

Problem: With 47 components, maintaining consistent horror aesthetics is hard.

Solution: Hook validates every component:

  • Colors match defined palette (--blood-red, --darkness, etc.)
  • Fonts use approved families (Creepster, Nosifer, Inter)
  • Animation durations follow standards
  • Accessibility requirements are met

Impact: Zero visual inconsistencies. Prevented "oops, I used the wrong red" mistakes.

4. Deployment Hook

Problem: Deployment had 15 manual steps. Easy to forget something.

Solution: One command automates:

  • TypeScript type checking
  • Test suite execution
  • Production build
  • Asset optimization
  • Vercel upload
  • Deployment notification

Impact: Deployment time: 15 minutes โ†’ 2 minutes. Zero human error.

The Hook Workflow

// Example: Image Optimization Hook
// /.kiro/hooks/optimize-images.hook.js

export async function onImageFetch(image) {
  const optimized = await sharp(image)
    .resize(500, null, { withoutEnlargement: true })
    .jpeg({ quality: 80 })
    .toBuffer();

  const webp = await sharp(image)
    .resize(500, null, { withoutEnlargement: true })
    .webp({ quality: 80 })
    .toBuffer();

  return {
    jpeg: optimized,
    webp: webp,
    srcset: generateSrcset(image)
  };
}
Enter fullscreen mode Exit fullscreen mode

Hooks transformed development from reactive (finding bugs after they happen) to proactive (preventing bugs automatically).


Part 3: Steering Docs (Teaching Kiro Your Standards)

Steering docs are like having a senior developer who knows your preferences sitting next to you. I created three:

1. Horror Theme Consistency

## Theme Requirements

**Typography:**
- Headings: Creepster (Google Fonts)
- Dripping text: Nosifer
- Body: Inter (readable despite horror theme)

**Colors:**
- Blood red: #DC143C (primary)
- Dark blood: #8B0000 (hover states)
- Pure black: #000000 (backgrounds)
- Bone white: #F5F5F5 (text)

**Forbidden:**
- Bright colors (no pure white backgrounds)
- Comic Sans or playful fonts
- Instant transitions (everything needs motion)
- Generic errors ("Error 404" โ†’ "The spirits are restless...")

**Examples:**

โŒ BAD:
return <div className="error">Error loading movie</div>

โœ… GOOD:
return (
  <motion.div 
    initial={{ opacity: 0 }}
    animate={{ opacity: 1 }}
    className="text-blood-red font-nosifer"
  >
    The spirits refuse to reveal this film...
  </motion.div>
)
Enter fullscreen mode Exit fullscreen mode

2. Code Quality Standards

## Code Requirements

- TypeScript: Strict mode, no 'any' types
- Components: Functional with hooks (no classes)
- Performance: No operations in render loops
- Accessibility: ARIA labels, keyboard navigation
- Testing: Every component has test file

## Patterns to Follow

- Custom hooks for reusable logic
- Context for global state
- Error boundaries around routes
- Lazy loading for route-level splitting
Enter fullscreen mode Exit fullscreen mode

3. Performance Targets

## Performance Requirements

- Animations: 60 FPS, fallback if dropping frames
- Images: Lazy load, WebP with JPEG fallback
- Bundle: <500KB gzipped
- API: Debounce search (500ms), cache responses
- Lighthouse: Score must stay >85
Enter fullscreen mode Exit fullscreen mode

The Magic: Negative Examples

The breakthrough was showing Kiro what NOT to do:

โŒ BAD: Linear animations (robotic)
โœ… GOOD: Easing functions (natural motion)

โŒ BAD: Autoplay sound (annoying)
โœ… GOOD: User-initiated audio (respectful)

โŒ BAD: "Loading..." (generic)
โœ… GOOD: "Summoning spirits..." (thematic)
Enter fullscreen mode Exit fullscreen mode

Impact: Before negative examples, 30% of generated components needed corrections. After: 5%.

Steering docs taught Kiro my aesthetic vision and technical standards, eliminating back-and-forth.


Part 4: Vibe Coding (Creative Polish)

Specs are perfect for logic. But for creative polish? Vibe coding shines.

Example: Blood Physics Refinement

Spec gave me: Working blood animation

Vibe coding gave me: Realistic blood physics

Conversation with Kiro:

Me: "The blood feels too uniform. Real blood has variation."

Kiro: Adds random droplet sizes

Me: "Good! But the fall speed should vary with size. Larger drops fall faster."

Kiro: Implements terminal velocity based on droplet mass

Me: "Perfect. Now add slight wind driftโ€”like 5-10 pixels left or right."

Kiro: Adds random horizontal velocity with damping

Me: "Amazing. The splatter needs more chaos thoughโ€”some particles should bounce."

Kiro: Adds collision detection and restitution coefficient

Result: Blood that looks genuinely realistic. This creative refinement doesn't belong in specsโ€”it's experimentation.


The Hybrid Approach: Specs + Vibe Coding

I used both strategically:

Specs for:

  • โœ… Complex logic (search, watchlist, player controls)
  • โœ… Performance requirements (FPS, load times)
  • โœ… Consistency (theme, accessibility)
  • โœ… Testing (acceptance criteria โ†’ test cases)

Vibe Coding for:

  • โœ… Creative exploration ("What if particles had random trajectories?")
  • โœ… Aesthetic refinement ("Make this feel more ominous")
  • โœ… Quick experiments (testing ideas without formal specs)

The combination was more powerful than either alone.


The Results

Technical Achievement

  • Duration: 21 days
  • Code: 5,234 lines of TypeScript
  • Components: 47
  • Animations: 50+
  • Performance: Lighthouse 94/100, 60 FPS consistent
  • Bundle: 387KB gzipped

Hackathon Success

  • ๐Ÿ† Best Costume Contest: $5,000
  • ๐Ÿ† Most Creative: $2,500
  • ๐Ÿฅˆ Overall 2nd Place: $20,000
  • Total: $27,500

Beyond Hackathon

  • 234 GitHub stars in first week
  • Featured on Product Hunt (3rd product of the day)
  • TechCrunch mention
  • 2 acquisition offers (including from Shudder!)

Key Lessons

1. Specs Eliminate Ambiguity

"Make it look good" โ†’ 10 iterations

"Follow this spec" โ†’ 1 iteration

Write precise specifications. Kiro will deliver precisely.

2. Automate Everything Possible

Manual testing wastes time. Hooks catch issues automatically.

Set up hooks early. They pay dividends immediately.

3. Teach Kiro Your Standards

Generic prompts โ†’ generic results

Steering docs โ†’ results that match your vision

Show negative examples. "Don't do X" is as important as "Do Y."

4. Combine Approaches

Specs for structure. Vibe coding for polish.

Use the right tool for each task. Don't force one approach for everything.

5. The .kiro Directory is Gold

Track it in Git. Show judges. Proves systematic AI usage.

My .kiro directory convinced judges I used Kiro strategically, not just as a fancy autocomplete.


The Future: Themed Entertainment Platforms

Blood Stream proves themed platforms are viable.

Horror today. Thriller tomorrow. Sci-Fi next week.

Netflix works for everything. But specialists could work better for specific genres.

Imagine:

  • Mystery Stream: UI like a detective's case board
  • Western Stream: Old saloon aesthetics
  • Sci-Fi Stream: Holographic interfaces

Each genre has superfans who'd pay premium for immersive experiences.

Blood Stream is just the beginning.


Try It Yourself

Live Demo: https://bloodstream.vercel.app

Source Code: [GitHub link]

Kiro Specs: Check the /.kiro directory

Tech Stack:

  • React 18 + TypeScript
  • TMDb API (free!)
  • Framer Motion
  • Tailwind CSS
  • Kiro AI

Final Thoughts

AI coding isn't about prompting. It's about structured specifications that eliminate ambiguity.

Kiro didn't just speed up codingโ€”it changed how I think about development:

  • Before: Write code โ†’ test โ†’ debug โ†’ rewrite
  • After: Write spec โ†’ Kiro generates โ†’ test โ†’ ship

The difference? Confidence.

With Kiro's spec-driven approach, agent hooks, and steering docs, I knew code would work before running it.

That confidence let me ship Blood Stream in 21 days.

What will you build?


#kiro #ai #webdev #hackathon #react #typescript


Built for Kiroween 2025.All in 21 days with Kiro AI.

Want to learn more? Follow me for updates on themed entertainment platforms and AI-assisted development.


Top comments (0)