DEV Community

Cover image for "Building NecroOS: A Haunted Windows 95 Simulator with Kiro AI"
Aryan
Aryan

Posted on

"Building NecroOS: A Haunted Windows 95 Simulator with Kiro AI"

 # Building NecroOS: A Haunted Windows 95 Simulator with Kiro AI

What if your computer was haunted? Not just buggy—actually possessed. That 2 AM thought turned into NecroOS, a horror game disguised as a Windows 95 desktop simulator. And I built it using Kiro AI's spec-driven development workflow.

🎃 The Concept

NecroOS starts as a comforting Windows 95 desktop—teal wallpaper, chunky pixels, satisfying clicks. But gradually, subtly, things go wrong. Your cursor drifts. The calculator gives you 2+2=5. Files appear in folders you just emptied. The horror isn't in-your-face—it's the creeping dread of familiar technology betraying you.

Live Demo: necro-os.vercel.app

Source Code: github.com/AstaadDahiya/Necro-OS

🛠️ The Tech Stack

  • Vue 3 + Pinia for reactive state management
  • Google Gemini AI (2.5 Flash) for Cursed Clippy, Spirit Board, and Soul Scanner
  • Web Audio API for 4-layer dynamic audio mixing
  • 98.css for authentic Windows 95 styling
  • Vite for blazing-fast development
  • Vercel for deployment

The numbers: 37,529 lines of code, 171 files, 11 functional apps, 4 difficulty modes, multiple endings.

🎯 The Kiro Difference: Spec-Driven Development

Here's where it gets interesting. I didn't just "vibe code" this project. I used Kiro AI's spec-driven workflow, which completely transformed how I build software.

The Traditional Approach (Vibe Coding)

Me: "Add some spooky audio effects"
Kiro: "What kind of effects? How should they trigger?"
Me: "Uh... whispers? When things get scary?"
Kiro: [Generates basic audio player]
Me: "Actually, I need multiple layers that blend dynamically..."
Kiro: [Refactors]
Me: "And it needs to scale with possession level..."
Kiro: [Refactors again]
Enter fullscreen mode Exit fullscreen mode

Result: 3 iterations, inconsistent implementation, no clear architecture.

The Spec-Driven Approach

Instead, I created 4 comprehensive specs that became my project's blueprint:

  1. necro-os - Base operating system
  2. necro-os-advanced-haunting - Possession mechanics (22 tasks)
  3. necro-os-visual-corruption - CRT effects and glitches
  4. necro-os-progressive-corruption - Level-based haunting

Each spec had three documents:

1. requirements.md - The "What"

Using EARS format (Easy Approach to Requirements Syntax):

## Requirement 1: Possession Level System

**User Story**: As a player, I want the haunting to gradually intensify, 
so that I experience escalating horror over time.

**Acceptance Criteria**:
1. THE System SHALL track possession level from 0 to 100
2. WHEN possession reaches 30, THE System SHALL trigger cursor corruption
3. WHILE game runs, THE System SHALL increase possession by 1.5 points/min
Enter fullscreen mode Exit fullscreen mode

2. design.md - The "How"

Technical architecture with formulas:

## Possession Level Formula

$$\Delta P = 1.5 \times m_d \times \frac{\Delta t}{60000}$$

Where:
- $\Delta P$ = possession increase
- $m_d$ = difficulty multiplier (Tourist: 0.5x, Nightmare: 3.0x)
- $\Delta t$ = time elapsed (ms)

## Audio Volume Scaling

$$V(P) = V_{\text{base}} \times (1 + 0.05 \times P)$$
Enter fullscreen mode Exit fullscreen mode

3. tasks.md - The "When"

Actionable implementation checklist:

- [ ] 1. Set up Pinia store structure
- [ ] 2. Implement possession tracking with formula
  - Use setInterval for continuous updates
  - Apply difficulty multiplier
  - _Requirements: 1.1, 1.2, 1.3_
- [ ] 3. Add threshold watchers (30, 45, 70, 80, 100)
Enter fullscreen mode Exit fullscreen mode

The Workflow in Action

Phase 1: Define requirements → "What should it do?"
Phase 2: Design architecture → "How should it work?"
Phase 3: Break into tasks → "What's the implementation order?"
Phase 4: Execute → "Implement task 2.1"
Enter fullscreen mode Exit fullscreen mode

When I said "implement task 2.1", Kiro read all three docs and generated production-ready code with full context. No clarifying questions. No iterations.

💡 Strategic Prompt Engineering

The quality of AI-generated code is directly proportional to the context you provide. Here's what I learned:

❌ Vague Prompt

"Create an audio system"
Enter fullscreen mode Exit fullscreen mode

✅ Precision Prompt

"Create a 4-layer audio haunting system using Web Audio API with independent 
gain nodes for ambient, effects, whispers, and tension. Scale volume using 
V = baseVolume × (1 + 0.05 × possessionLevel). Handle browser autoplay 
restrictions with lazy initialization. Integrate with Pinia advancedHaunting 
store for reactive updates."
Enter fullscreen mode Exit fullscreen mode

The result: Kiro generated a complete, optimized audio system in one shot—Web Audio API architecture, gain nodes, volume formulas, autoplay handling, Pinia integration, error handling, and JSDoc documentation.

🎨 The Horror Mechanics

Possession System

Everything revolves around one number: possession level (0-100). It drives all horror effects:

  • 30%: Cursor starts drifting
  • 45%: Wallpaper flickers
  • 70%: Whispers and phantom notifications
  • 80%: Heartbeat tension, full chaos
  • 100%: Possessed ending

4-Layer Audio System

Instead of random spooky sounds, I built a dynamic audio architecture:

class AudioHauntingService {
  layers = {
    ambient: { baseVolume: 0.3 },  // Background dread
    effects: { baseVolume: 0.5 },  // Phantom typing, HDD grinding
    whispers: { baseVolume: 0.2 }, // Barely audible voices
    tension: { baseVolume: 0.4 }   // Pre-jumpscare heartbeat
  }

  updateVolume(possessionLevel) {
    Object.entries(this.layers).forEach(([name, layer]) => {
      const multiplier = 1 + (0.05 * possessionLevel)
      const newVolume = layer.baseVolume * multiplier
      layer.gainNode.gain.setValueAtTime(newVolume, this.audioContext.currentTime)
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Volume scales with possession level, creating audio that responds to gameplay.

Exorcism Mechanics

Players aren't helpless:

  1. Text Exorcism: Type "begone spirit" (-15 possession)
  2. File Exorcism: Delete cursed files (-8 possession)
  3. Puzzle Exorcism: Complete symbol sequences in 30s (-20 possession)

Each has a 2-minute cooldown, creating strategic gameplay.

AI Integration with Gemini

Three apps use Google Gemini AI:

Cursed Clippy: Sarcastic AI assistant with command execution

systemPrompt: `You are Cursed Clippy, a sarcastic AI haunting a Windows 95 
desktop. Make references to being trapped. Use 90s internet culture. 
Execute commands via [COMMAND:action:target] syntax.`
Enter fullscreen mode Exit fullscreen mode

Spirit Board: Ouija board with AI-generated responses

prompt: `You are a spirit communicating through a Ouija board. 
Respond in max 30 characters. Use only letters, numbers, spaces.`
Enter fullscreen mode Exit fullscreen mode

Soul Scanner: Webcam facial expression analysis with Gemini Vision API

prompt: `Analyze this person's expression in one cryptic sentence (max 15 words). 
If happy, threaten them. If scared, mock them. If neutral, make eerie observations.`
Enter fullscreen mode Exit fullscreen mode

📊 The Results

Time Comparison:

  • Planning with specs: 2 hours
  • Implementation: 6 hours (22 tasks)
  • Refactoring: 30 minutes
  • Total: 8.5 hours

Without specs: Estimated 20+ hours with multiple rewrites

Quality Improvements:

  • ✅ Got it right the first time (minimal refactoring)
  • ✅ Consistent architecture across all features
  • ✅ Built-in documentation
  • ✅ Clear definition of "done"
  • ✅ Easy to resume after breaks

🎓 Key Lessons

1. Spec-Driven > Vibe Coding for Complex Projects

Specs aren't slower—they're front-loaded thinking. Spend 2 hours planning to save 12 hours refactoring.

2. Specificity Beats Brevity in Prompts

  • Bad: "Make it faster"
  • Good: "Batch DOM updates using requestAnimationFrame to maintain 60 FPS"

3. Context Persistence is Everything

Specs gave Kiro a complete mental model. Each conversation built on the last. No context loss between sessions.

4. Accessibility in Horror is Possible

I added photosensitivity warnings, reduced motion mode, and keyboard navigation without losing the scary parts.

5. Audio is 50% of Horror

Investing in the Web Audio API multi-layer system paid huge dividends. Simple <audio> tags wouldn't have cut it.

🚀 What's Next

I'm planning:

  • Multiplayer haunting where possession spreads between users
  • Procedural jumpscare generation using AI
  • VR support for truly immersive terror
  • More endings based on player choices

💭 Final Thoughts

NecroOS started as a weird 2 AM idea and turned into the most complex project I've built. But the real story isn't the horror game—it's discovering that spec-driven development with AI is a game-changer.

Kiro didn't build NecroOS. I architected it through strategic prompts and specs. Kiro implemented my vision.

That's the difference between "AI wrote my code" and "I used AI as a force multiplier for my ideas."

The haunting is just beginning. 👻


Try it: necro-os.vercel.app

Source: github.com/AstaadDahiya/Necro-OS

Built with: Vue 3, Gemini AI, Kiro, and way too much coffee ☕

kiro #ai #webdev #gamedev #vue #horror

Top comments (0)