Building My First RAG System in One Week with Kiro IDE 🎃

Published: (December 2, 2025 at 01:26 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

🎃 The Challenge

As a junior apps developer, I’d never built a RAG (Retrieval Augmented Generation) system before. The concept seemed intimidating: vector embeddings, semantic search, chunking strategies—all foreign territory. But the Kiroween hackathon’s “Skeleton Crew” category sparked an idea: what if I could build ONE reusable skeleton that transforms into ANY AI personality?

Seven days later, I had Project Corpus: a production‑ready RAG chatbot that can become a professional legal assistant, a mystical spirit, or anything else—just by swapping a config file.

🔗 Live Demo | GitHub Repo

🔮 What is Project Corpus?

Project Corpus is a document‑chat application with a twist: the same core logic powers radically different AI personalities.

Two Personalities, One Skeleton

⚖️ Legal Eagle

  • Professional legal document analysis
  • Formal responses with precise citations
  • Blue corporate styling with typewriter sounds
  • Ideal for contract analysis and legal research

👻 Ouija Board

  • Mystical document exploration “from beyond the veil”
  • Cryptic, atmospheric responses with spooky emojis
  • Dark gothic theme with blood‑drip animations
  • Ambient drone audio with static glitch effects

Both apps share the same skeleton_core module—only the config changes.

🛠️ The Tech Stack

Backend

  • Python 3.13 + Flask 3.1.0
  • ChromaDB 0.5.20 (vector database)
  • Google Gemini API 0.8.3 (embeddings + generation)
  • pypdf 5.1.0 (PDF processing)

Frontend

  • Vanilla JavaScript (no frameworks)
  • Custom CSS with theme variables
  • Server‑Sent Events for real‑time progress

Testing

  • pytest 7.4.3
  • hypothesis 6.92.1 (property‑based testing)

Development

  • Kiro IDE (the secret weapon 🚀)

🤖 How Kiro Transformed My Development

1. 🎨 Vibe Coding: Learning While Building

As a junior developer, I needed to understand RAG, not just write code. Kiro’s conversational approach let me learn and build simultaneously.

Example conversation

Me: "How do I chunk PDFs by page and preserve page numbers?"
Kiro: *Explains chunking strategies, then generates code that:*
- Extracts PDF pages individually
- Chunks each page with 500 char / 50 overlap
- Stores metadata with source, page, chunk_index
- Retrieves page numbers in search results

Most Impressive Generation

Kiro produced the entire Server‑Sent Events upload pipeline in one conversation, including:

  • Flask SSE streaming with Response(stream_with_context())
  • 4‑stage progress calculation (reading, parsing, vectorizing, finalizing)
  • Client‑side EventSource listener with progress bars
  • Graceful error handling

I had never used SSE before; Kiro not only wrote the code but also explained why SSE beats polling for this use case.

2. 📋 Specs: Systematic UI Polish

After building core features with vibe coding, I created .kiro/spec.md describing the desired user experience:

## 4. Implemented Features
1. **Document Upload (`/upload`):**
   - Real‑time progress tracking via SSE
   - Page‑aware chunking with metadata
   - File validation (type, size, content)

2. **Chat Interface (`/chat`):**
   - Semantic search with relevance filtering
   - Source citations with page numbers
   - Typewriter effect for responses

With the spec in place, I could say “implement section 4.1” and Kiro would systematically add all features—no back‑and‑forth needed.

Vibe Coding vs. Specs

  • Vibe Coding: Exploratory, great for learning and core features.
  • Specs: Systematic, perfect for polish and completeness.

3. 📚 Steering Docs: Teaching Kiro My Architecture

I created four steering documents that taught Kiro the project’s DNA.

structure.md – The game‑changer

### Skeleton + Config Pattern

The `skeleton_core` module contains all shared RAG functionality.  
Individual app folders provide configuration objects that customize behavior.

Each `app_*/config.py` must define:
- `APP_NAME`: String for branding  
- `THEME_CSS`: CSS theme identifier  
- `SYSTEM_PROMPT`: AI personality instructions  
- `CHUNK_SIZE`, `CHUNK_OVERLAP`, `TOP_K_RESULTS`, `RELEVANCE_THRESHOLD`

Before steering docs

  • Me: “Add a delete document feature”
  • Kiro: Modifies app_legal/main.py directly ❌ (breaks reusability)

After steering docs

  • Me: “Add a delete document feature”
  • Kiro: Adds delete_document() to skeleton_core/vector_store.py, creates /documents/ DELETE route, updates frontend ✅ (maintains skeleton pattern)

Steering docs reduced “wrong suggestions” by ~80%, turning Kiro into a partner who understood the project’s philosophy, not just its syntax.

4. 🪝 Agent Hooks: Automated Quality Assurance

I built five hooks that caught bugs before deployment.

test-runner-on-save.kiro.hook

{
  "when": { "type": "fileEdited", "patterns": ["**/*.py"] },
  "then": { "type": "runCommand", "command": "pytest --tb=short -q" }
}

Runs tests automatically on every save, catching breaking changes instantly.

config-validator.kiro.hook – Validates that config files contain all required fields, preventing runtime errors.

env-check-on-session.kiro.hook – Verifies GOOGLE_API_KEY exists on session start, saving minutes of debugging.

Impact – Shifted workflow from reactive debugging to proactive validation, providing a safety net for a junior developer.

🧟 The Biggest Challenges

1. RAG Learning Curve

Understanding vector embeddings, semantic search, and chunking was overwhelming. Kiro became my teacher, offering explanations and solutions when search results were irrelevant.

Solution: Implemented relevance filtering that only shows documents within 0.3 distance units of the best match, ensuring accurate citations.

2. Page‑Aware Chunking

Preserving page numbers through extraction → chunking → embedding → storage → retrieval required careful metadata management.

Solution: Added page tracking at each stage with metadata, e.g.:

metadata = {
    "source": filename,
    "page": page_num,
    "chunk_index": i
}

3. Theme Switching Architecture

Supporting radically different personalities from a single codebase demanded strong abstraction.

Solution: Adopted a config‑based approach; adding a new personality now takes ~10 minutes.

🏆 What I’m Proud Of

1. Learning RAG in One Week

Went from zero RAG knowledge to a production‑ready system with vector search, embeddings, and semantic retrieval in 7 days. Kiro’s vibe coding made this possible.

2. The Skeleton Pattern Works

The architecture is genuinely reusable. Adding a new personality is as simple as:

mkdir app_detective
# Add config.py with Config class
# Add main.py entry point
# Done! 🎉

3. Production‑Quality UI

  • Smooth animations (typewriter effect, blood drips)
  • Real‑time upload progress with SSE
  • Document library with selective filtering
  • Accessibility (ARIA labels, keyboard navigation)
  • Theme‑specific audio (typewriter, ambient drone)
Back to Blog

Related posts

Read more »