DEV Community

Cover image for Building Integral: Full-Stack Productivity Suite with RAG & AI Assistant
Exyness
Exyness

Posted on

Building Integral: Full-Stack Productivity Suite with RAG & AI Assistant

Building Integral: How I Shipped a Full-Stack Productivity Suite in Weeks with AI-Assisted Development

Integral Banner

I just shipped Integral - a complete productivity platform with task management, budgeting, journaling, time tracking, and an AI assistant. The twist? I built it using Kiro, an AI-powered IDE that fundamentally changed how I approach development.

This isn't a "look what AI can do" post. It's an honest breakdown of what worked, what didn't, and the specific techniques that made the difference.

What I Built

Integral is an all-in-one productivity suite with:

  • Tasks with Kanban boards, calendar views, and "zombie task resurrection"
  • Notes with a Lexical rich text editor and folder organisation
  • Budget with multi-currency tracking and analytics
  • Journal with mood tracking and daily reflections
  • Pomodoro timer with session history
  • Time Tracking with activity logging
  • Accounts for secure credential storage
  • AI Chat Assistant with 12 command shortcuts

Plus a Halloween theme mode because why not.

Halloween themed Tasks

The Numbers:

  • ~70% of initial code generated by Kiro
  • ~20% custom logic I wrote
  • ~10% iterative refinement together
  • 14 comprehensive specs with 200+ implementation tasks
  • 3,774 modules transformed
  • Total bundle: 2.2MB raw / 635KB gzipped (main bundle)
  • Largest chunks: Finances (321KB), Landing (150KB), React vendor (167KB)

The Tech Stack

Frontend: React 19.2 + TypeScript 5.9, Vite 7.2, Tailwind CSS 4.1, Framer Motion 12.23, TanStack Query v5 + React Context, Lexical 0.38

Backend: Supabase (PostgreSQL), Supabase Auth with RLS, Supabase Subscriptions

Quality: Biome 2.3.5 (replaces ESLint + Prettier), Zod 4 + React Hook Form 7.66

Budget Page

The Secret Weapon: Steering Docs

Here's what changed everything. Instead of repeating myself in every conversation, I created three "steering docs" that Kiro always reads:

.kiro/steering/structure.md - The game changer:

## State Management

- TanStack Query for server state (queries, mutations, caching)
- React Context for global UI state (theme, auth, currency, network)
- Local state with `useState` for component-specific state
- Query keys follow pattern: `[entity, userId]` (e.g., `["tasks", user?.id]`)

## Styling

- Tailwind CSS utility classes
- Glass morphism design system via `GlassCard` component
- Dark/light theme support via `ThemeContext`
- Halloween mode with teal accent color (#60c9b6)
- Responsive design with mobile-first approach

## Halloween Theme

- Check `isHalloweenMode` from `useTheme()` hook
- Apply teal color (#60c9b6) for accents
- Use Creepster font for titles
- Add drop shadow glows for spooky effects
Enter fullscreen mode Exit fullscreen mode

Why this worked: Every new component Kiro generated automatically followed these patterns. No more "remember to use TanStack Query" or "don't forget the Halloween theme." It just knew.

The Halloween theme support was particularly impressive - Kiro consistently added theme-aware styling to every component because the steering doc made it standard practice.

Show Me The Code: GlassCard Component

Here's the GlassCard component that powers the entire UI. Kiro generated the initial version, I refined the variants:

interface GlassCardProps extends React.HTMLAttributes<HTMLDivElement> {
  children: React.ReactNode;
  variant?: "primary" | "secondary" | "tertiary";
  hover?: boolean;
}

export const GlassCard: React.FC<GlassCardProps> = ({
  children,
  variant = "primary",
  hover = false,
  ...props
}) => {
  const { isDark, isHalloweenMode } = useTheme();

  const darkVariants = {
    primary: "bg-[rgba(25,25,30,0.85)] backdrop-blur-[20px] border-[rgba(255,255,255,0.15)]",
    secondary: "bg-[rgba(35,35,40,0.75)] backdrop-blur-lg border-[rgba(255,255,255,0.12)]",
    tertiary: "bg-[rgba(45,45,50,0.65)] backdrop-blur-md border-[rgba(255,255,255,0.1)]"
  };

  const halloweenClasses = isHalloweenMode
    ? "border-[rgba(96,201,182,0.2)] shadow-[0_0_20px_rgba(96,201,182,0.15)]"
    : "";

  return (
    <div className={`rounded-lg border transition-all ${darkVariants[variant]} ${halloweenClasses}`}>
      {children}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

This component is used everywhere - every card, modal, and panel. Consistent glass morphism across 8 major features with zero duplication.

Notes Page

The AI Chat Widget: 63 Tasks, 17 Phases

The most complex feature was the AI chat assistant. Here's where spec-driven development saved me.

The Challenge: Build a conversational AI that can:

  • Parse 12 different command types
  • Handle multi-step flows (e.g., collecting password without sending it to AI)
  • Coordinate with other widgets (timer repositions when chat opens)
  • Support natural language AND command shortcuts
  • Work across all themes

The Solution: A comprehensive spec with:

  • requirements.md: 18 user stories with acceptance criteria
  • design.md: Architecture diagrams, data models, correctness properties
  • tasks.md: 63 implementation tasks across 17 phases

Sample from the spec:

### Phase 6: Pending Action System for Multi-Step Flows

- [x] 15. Create PendingAction interface and state
- [x] 16. Implement context-specific prompts
- [x] 17. Implement field collection flow
  - Check if user response fills missing field
  - Update pendingAction.params with user input
  - Remove filled field from missingFields array
  - Prompt for next missing field if any remain
  - Execute action when all fields collected
Enter fullscreen mode Exit fullscreen mode

Without this structure, I would've lost track of requirements. The spec kept both me and Kiro aligned.

Journal Page

The AI Assistant Hook: Type-Safe Intent Detection

Here's how the AI chat actually works under the hood:

export type AIIntent =
  | "create_task"
  | "create_note"
  | "create_journal"
  | "create_transaction"
  | "create_budget"
  | "create_goal"
  | "transfer_funds"
  | "create_account"
  | "general_chat";

interface AIResponse {
  intent: AIIntent;
  params: Record<string, unknown>;
  confirmationMessage: string;
}

export const useAIAssistant = () => {
  const processQuery = async (query: string): Promise<AIResponse> => {
    const prompt = `Analyze this user query and extract intent and parameters:
    "${query}"

    Available intents: ${AIIntent}
    Return JSON with: { intent, params, confirmationMessage }`;

    const result = await ai.generateContent(prompt);
    return JSON.parse(result.response.text());
  };

  return { processQuery };
};
Enter fullscreen mode Exit fullscreen mode

What Kiro did well: Generated the type definitions and basic structure.

What I had to fix: The prompt engineering. Initial version was too generic and misclassified intents. I added specific examples and constraints to improve accuracy.

Pomodoro Page

What Didn't Work: The Honest Truth

1. Agent Hooks Became Less Useful Over Time

I configured 8 automated hooks:

  • lint-fix-on-save ✅ (consistently useful)
  • bundle-size-check ✅ (helpful for monitoring)
  • accessibility-review ⚠️ (too generic)
  • component-test-reminder ❌ (annoying)
  • halloween-testing-checklist ❌ (too specific)

The lesson: As the codebase grew, I needed context-aware assistance, not automated reminders. Direct conversations with Kiro were more valuable than hooks firing on every save.

2. Kiro Struggled with Complex State Logic

The fund transfer feature required:

  • Normalized account name matching
  • Balance validation
  • Atomic updates to two accounts
  • Transaction record creation
  • Query cache invalidation

Kiro generated a working first pass, but I had to refactor the error handling and add proper rollback logic. AI is great at structure, less great at edge cases.

3. Initial Specs Were Too Detailed

My first spec had 200+ acceptance criteria. It was overwhelming. I learned to:

  • Start with high-level requirements
  • Add details as I implement
  • Use "correctness properties" instead of exhaustive test cases

Accounts Page

Spec-Driven vs Vibe Coding: When to Use Each

I used two approaches throughout the project:

Spec-Driven Development (for complex features):

  • Authentication system
  • AI chat widget (63 tasks)
  • Budget tracking with multi-currency
  • Rich text editor integration

Vibe Coding (for everything else):

  • UI polish and animations
  • Bug fixes
  • Styling tweaks
  • Refactoring

The Rule: If a feature has more than 3 components or requires coordination between systems, write a spec. Otherwise, just talk to Kiro.

Bundle Optimization:

  • Manual chunk splitting (react-vendor, router-vendor, ui-vendor, supabase-vendor)
  • Lazy loading for all routes (Tasks, Notes, Budget, etc. load on demand)
  • Virtualized lists for large datasets (react-virtuoso) & Tanstack Virtual
  • Optimistic updates for instant UI feedback
  • Code splitting reduced initial load to ~635KB gzipped

Time Tracking Page

Unique Features Worth Stealing

1. Zombie Task Resurrection

Tasks overdue by 7+ days become "zombie tasks." Click the resurrection button to break them into smaller subtasks:

const zombieTasks = tasks.filter((task) => {
  const daysOverdue = differenceInDays(new Date(), new Date(task.due_date));
  return !task.completed && daysOverdue >= 7;
});
Enter fullscreen mode Exit fullscreen mode

2. Context-Aware AI Placeholders

The AI chat input changes based on your current page:

const getPlaceholder = () => {
  const path = location.pathname;
  if (path.includes("/tasks")) return "@task Add project deadline...";
  if (path.includes("/notes")) return "@note Save this idea...";
  if (path.includes("/budget")) return "@transaction Spent $50 on...";
  return "Type @ for commands or ask anything...";
};
Enter fullscreen mode Exit fullscreen mode

3. Multi-Currency Budget Tracking

Supports multiple currencies with real-time conversion:

interface Transaction {
  amount: number;
  currency: string; // USD, EUR, GBP, etc.
  converted_amount: number; // Always in user's base currency
  exchange_rate: number;
}
Enter fullscreen mode Exit fullscreen mode

The Development Timeline

October 30 - December 3, 2024 (~5 weeks)

Built for the Kiro hackathon, here's how it went down:

Week 1 (Oct 30 - Nov 5): Project setup, authentication, and Tasks page (spec-driven)
Week 2 (Nov 6-12): Notes with Lexical editor + Budget tracking (spec-driven)
Week 3 (Nov 13-19): Journal, Pomodoro, Time Tracking (mix of spec + vibe)
Week 4 (Nov 20-26): AI Chat Widget with 12 commands (spec-driven, 63 tasks)
Week 5 (Nov 27 - Dec 3): Dashboard, Halloween theme, polish, and deployment

Key Takeaways

  1. Steering docs are 10x multipliers. Write them once, benefit forever.

  2. Specs prevent scope creep. Complex features need structure. The AI chat widget would've been impossible without 63 documented tasks.

  3. AI struggles with edge cases. Great at structure, needs human oversight for error handling and validation.

  4. Context is everything. Using @ mentions to reference existing files maintained consistency across 14 specs.

  5. Iterate on what works. Hooks were useful early on but became less relevant. Adapt your workflow as the project evolves.

  6. Show, don't tell. Code snippets > process descriptions. Developers want to copy-paste patterns.

Try It Yourself

Live Demo: Integral Beta
GitHub: Repository Link
Demo Account: demo@integral.com / integral

What's Next?

I'm working on:

  • Mobile apps (React Native with shared business logic)
  • Offline-first sync with conflict resolution
  • Team collaboration features
  • AI-powered insights and recommendations

The Bottom Line

Kiro generated ~70% of the code. But the real value wasn't code generation - it was maintaining consistency across 14 specs, 8 features, and 3 themes without me having to repeat myself.

The future of development isn't human vs AI. It's human + AI, each doing what they do best:

  • AI: Structure, patterns, boilerplate
  • Human: Edge cases, UX decisions, architecture

If you're building something complex, try this workflow:

  1. Write steering docs for your patterns
  2. Use specs for multi-component features
  3. Vibe code for everything else
  4. Iterate based on what works

The results might surprise you.


Built with: React 19, TypeScript, Supabase, Kiro, and way too much coffee ☕

Questions? Drop them in the comments. I'll share more code snippets and specific techniques.

Top comments (1)

Collapse
 
kochmeierd profile image
Daniel Kochmeier

Incredible work! Integral looks insanely well thought out and polished—kudos for shipping such a full-featured suite in weeks. I’d love to see a direct integration with the TimeSpin Tracker Dice—there’s something so satisfying about the tactile experience of tracking time that would make using Integral even more fun.