Skip to content

Starter Repo for OneEthos's 'Building Delightful AI Chat Applications w/ Dynamic UI' Workshop at KnightHacks XIII

Notifications You must be signed in to change notification settings

oneethosdev/impact-chatkit-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Impact AI - Financial Impact & Values-Aligned Spending Assistant

Values Alignment
Impact AI Dashboard
Transaction Analysis

A modern, open-source financial assistant powered by AI that helps users explore their transactions, discover merchants that align with their personal values, and make more intentional spending decisions.

This repo serves as the starter for the Building Delightful AI Chat Applications w/ Dynamic UI' Workshop at KnightHacks XIII, and allows hackers to easily add functionality or create dynamic UI chat apps for other use-cases.

🎯 What is Impact AI?

Impact AI is a conversational chatbot that combines spending analytics with values-based insights. Users can:

  • Explore transactions - Search and visualize spending patterns by category, merchant, or time period
  • Discover aligned merchants - Find companies matching their personal values (e.g., women-owned, sustainable, local)
  • Define personal values - Create a personal values profile and track spending alignment
  • Compare spending - Analyze spending between different company types or values categories
  • Get recommendations - Receive suggestions for alternative merchants that align with their values

πŸ—οΈ Project Architecture

impact-chatkit-starter/
β”œβ”€β”€ backend/                 # Python FastAPI + AI agent
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ agent/          # ChatKit agent & modular tools
β”‚   β”‚   β”œβ”€β”€ services/       # Data access layer
β”‚   β”‚   β”œβ”€β”€ main.py         # FastAPI entrypoint
β”‚   β”‚   β”œβ”€β”€ chat.py         # ChatKit server & agent setup
β”‚   β”‚   β”œβ”€β”€ database.py     # Prisma database layer
β”‚   β”‚   └── constants.py    # AI instructions & configuration
β”‚   β”œβ”€β”€ prisma/
β”‚   β”‚   β”œβ”€β”€ schema.prisma   # Database models
β”‚   β”‚   └── seed.py         # Sample data generator
β”‚   └── widgets/            # Reusable JSON widget templates
β”‚
β”œβ”€β”€ frontend/               # React + Vite + TypeScript
β”‚   └── src/
β”‚       β”œβ”€β”€ components/     # React components
β”‚       β”œβ”€β”€ hooks/          # Custom React hooks
β”‚       └── lib/            # Config and utilities
β”‚
└── docker-compose.yml      # Local dev environment (PostgreSQL + backend + frontend)

πŸš€ Quick Start

Prerequisites

  • Docker & Docker Compose (recommended for local dev)
    • OR: Node.js 18+, Python 3.11+, PostgreSQL 14+
  • OpenAI API Key (required for AI agent)

Option 1: Docker Compose (Recommended)

# Clone the repository
git clone https://github.com/KnightHacks/impact-chatkit-starter.git
cd impact-chatkit-starter

# Set environment variables
cp backend/.env.example backend/.env  # Add your API keys

# Start all services (PostgreSQL, backend, frontend)
docker-compose up --build -d

# Frontend: http://localhost:5170
# Backend API: http://localhost:8000

Option 2: Local Development

Backend:

cd backend
uv sync  # Install dependencies
uv run uvicorn app.main:app --reload --port 8000

Frontend:

cd frontend
npm install
npm run dev  # Runs on http://localhost:5173

Database:

# Set DATABASE_URL in backend/.env
# Run migrations
cd backend
uv run python prisma/seed.py

πŸ“‹ How It Works

1. User Message Flow

User Input β†’ ChatKit Frontend β†’ Backend /chatkit endpoint β†’ OpenAI Agent

2. Agent Processing

The AI agent processes user queries and invokes available tools:

# Examples of agent interactions
"Show my restaurant spending last week"
β†’ show_transactions(query="restaurant last week")

"Find women-owned sustainable clothing brands"
β†’ show_companies(tags=['women-owned', 'sustainable'], category='Retail')

"Compare my spending at women-owned vs chain restaurants"
β†’ compare_spending(filter_a={...}, filter_b={...})

3. Data Visualization

All responses include JSON widgets rendered in the ChatKit UI:

  • Transaction lists - Detailed transaction history with filters
  • Company cards - Company info with values/tags
  • Charts - Spending trends, comparisons, alignment metrics
  • Value dashboards - User's values + spending alignment

4. Database Layer

Prisma ORM manages three core models:

  • Users - Stores personal values & preferences
  • Companies - Merchant data + tags/values
  • Transactions - Spending history + merchant links

πŸ› οΈ Development Guide

Adding a New Tool

Tools are modular Python functions that the AI agent can invoke. They're registered in backend/app/chat.py.

1. Create a tool file backend/app/agent/tools/my_tool.py:

from agents import tool
from chatkit.agents import AgentContext
from typing import Annotated, Optional

@tool
async def analyze_savings(
    category: Annotated[str, "Spending category to analyze (e.g., 'Restaurant')"] = None,
    days: Annotated[Optional[int], "Days to look back (default 30)"] = None,
) -> dict:
    """Analyze potential savings in a spending category."""
    # Your implementation here
    return {
        "category": category,
        "savings_potential": 150.00,
        "savings_suggestions": ["Switch to cheaper restaurants", "Cook at home"]
    }

2. Register in chat.py:

# In app.chat.py - add to imports
from .agent.tools import analyze_savings

# In FactAssistantServer.__init__ - add to tools list
tools = [
    # ... existing tools ...
    analyze_savings,
]

3. Update agent instructions in constants.py:

INSTRUCTIONS = """
...
β€’ `analyze_savings(category?, days?)` β€” find potential savings in a category
  Returns: JSON with suggestions and estimated savings.
...
"""

Adding a New Widget

Widgets are JSON templates with support for dynamic data via {{variable}} syntax.

1. Design in Widget Builder:

2. Save template to backend/widgets/my_widget.json:

{
  "type": "Card",
  "padding": 4,
  "children": [
    { "type": "Title", "value": "{{title}}", "size": "lg" },
    { "type": "Text", "value": "Amount: ${{amount}}" }
  ]
}

3. Use in your tool:

from app.agent.utils import load_widget_from_file

widget = load_widget_from_file(
    "backend/widgets/my_widget.json",
    {"title": "Savings Summary", "amount": "150.00"}
)
await ctx.context.stream_widget(widget, copy_text="Summary text for history")

See backend/widgets/README.md for complete widget documentation.

Modifying Data Sources

All data queries go through the services layer in backend/app/services/.

To modify transaction queries:

# backend/app/services/transactions.py

async def get_transactions_by_merchant(
    user_id: str,
    merchant: str,
    days: int = 30
) -> list[Transaction]:
    """Fetch transactions for a specific merchant."""
    db = await get_database()
    cutoff_date = datetime.now() - timedelta(days=days)

    return await db.transaction.find_many(
        where={
            "userId": user_id,
            "merchantName": {"contains": merchant, "mode": "insensitive"},
            "date": {"gte": cutoff_date}
        },
        order={"date": "desc"}
    )

To modify company queries:

# backend/app/services/companies.py

async def search_companies_by_values(
    tags: list[str],
    category: str | None = None,
    limit: int = 10
) -> list[Company]:
    """Find companies matching specific values/tags."""
    db = await get_database()

    query = {
        "tags": {"hasSome": tags}
    }

    if category:
        query["category"] = category

    return await db.company.find_many(
        where=query,
        take=limit
    )

Seeding Sample Data

Edit backend/prisma/seed.py to add test users, companies, and transactions:

# backend/prisma/seed.py

async def main():
    db = Prisma()
    await db.connect()

    # Create test company
    await db.company.create({
        "data": {
            "name": "Sustainable Cafe",
            "category": "Restaurant",
            "tags": ["sustainable", "local", "women-owned"],
            "description": "Local cafe with sustainable practices"
        }
    })

    # Create test user
    user = await db.user.create({
        "data": {
            "name": "Test User",
            "email": "test@example.com",
            "values": ["sustainable", "women-owned"]
        }
    })

    # Create test transactions
    await db.transaction.create({
        "data": {
            "userId": user.id,
            "merchantName": "Sustainable Cafe",
            "amount": 15.50,
            "category": "Restaurant",
            "date": datetime.now()
        }
    })

    await db.disconnect()

asyncio.run(main())

Run seeding:

cd backend
uv run python prisma/seed.py

πŸ“± Frontend Architecture

Key Components

App.tsx - Root component managing theme state

Home.tsx - Page layout with header and ChatKit panel

ChatKitPanel.tsx - ChatKit integration + client-side tool handlers

useColorScheme.ts - Theme state management (light/dark)

config.ts - API endpoints and ChatKit configuration

Customizing the Frontend

Change theme colors in frontend/src/components/Home.tsx:

const containerClass = clsx(
  "min-h-screen transition-colors duration-300",
  scheme === "dark" ? "bg-slate-900 text-slate-100" : "bg-white text-slate-900"
);

Update API endpoints in frontend/src/lib/config.ts:

export const CHATKIT_API_URL =
  import.meta.env.VITE_CHATKIT_API_URL ?? "/chatkit";

Modify starter prompts in frontend/src/lib/config.ts:

export const STARTER_PROMPTS = [
  {
    label: "Your custom prompt",
    prompt: "Your prompt text",
    icon: "search",
  },
];

πŸ—„οΈ Database Schema

Users

CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT uuid(),
  name VARCHAR NOT NULL,
  email VARCHAR UNIQUE NOT NULL,
  values TEXT[] DEFAULT '{}',  -- e.g., ['women-owned', 'sustainable']
  createdAt TIMESTAMP DEFAULT NOW(),
  updatedAt TIMESTAMP DEFAULT NOW()
);

Companies

CREATE TABLE companies (
  id UUID PRIMARY KEY DEFAULT uuid(),
  name VARCHAR NOT NULL,
  category VARCHAR NOT NULL,           -- 'Restaurant', 'Retail', etc.
  description TEXT,
  logoUrl VARCHAR,
  tags TEXT[] DEFAULT '{}',            -- e.g., ['women-owned', 'sustainable', 'local']
  website VARCHAR,
  createdAt TIMESTAMP DEFAULT NOW(),
  updatedAt TIMESTAMP DEFAULT NOW()
);

Transactions

CREATE TABLE transactions (
  id UUID PRIMARY KEY DEFAULT uuid(),
  userId UUID NOT NULL,
  companyId UUID REFERENCES companies(id),
  merchantName VARCHAR NOT NULL,
  amount FLOAT NOT NULL,
  category VARCHAR NOT NULL,           -- 'Restaurant', 'Retail', 'Transport', etc.
  date TIMESTAMP NOT NULL,
  description TEXT,
  tags TEXT[] DEFAULT '{}',
  createdAt TIMESTAMP DEFAULT NOW()
);

πŸ” Environment Variables

Backend - backend/.env:

DATABASE_URL=postgresql://impactai:password@localhost:5432/impactai
OPENAI_API_KEY=sk-xxx...
CHATKIT_API_DOMAIN_KEY=domain_pk_xxx...

Frontend - Set via Docker or .env:

VITE_CHATKIT_API_URL=http://localhost:8000/chatkit
VITE_CHATKIT_API_DOMAIN_KEY=domain_pk_localhost_dev

πŸ“š Key Files Reference

File Purpose
backend/app/chat.py ChatKit server setup + tool registration
backend/app/constants.py AI agent instructions + tool definitions
backend/app/agent/tools/*.py Individual tool implementations
backend/app/services/*.py Database query logic
backend/widgets/*.json Widget templates for UI responses
frontend/src/components/ChatKitPanel.tsx ChatKit UI + client-side tool handling
docker-compose.yml Local dev environment config

πŸ› Troubleshooting

"ChatKit dependencies are missing"

  • Ensure openai-chatkit is installed: pip list | grep chatkit

Database connection errors

  • Check DATABASE_URL in backend/.env
  • Verify PostgreSQL is running: psql -U impactai -d impactai -c "SELECT 1"

Widgets not rendering

  • Check widget JSON syntax in backend/widgets/
  • Verify template variables in load_widget_from_file() calls

Agent not calling tools

  • Check tool registration in chat.py
  • Verify tool docstring for proper parameter descriptions
  • Check OpenAI API key in backend/.env

πŸ“– Additional Documentation

  • Backend: See backend/README.md
  • Frontend: See frontend/README.md
  • Widgets: See backend/widgets/README.md
  • Prisma: https://www.prisma.io/docs

πŸš€ Deployment

Docker:

docker build -f backend/Dockerfile -t impact-ai-backend ./backend
docker build -f frontend/Dockerfile -t impact-ai-frontend ./frontend
docker push your-registry/impact-ai-backend:latest
docker push your-registry/impact-ai-frontend:latest

Production Setup:

  • Use managed/hosted PostgreSQL
  • Set production OpenAI API key
  • Use proper ChatKit domain key registered at https://platform.openai.com
  • Enable CORS for your frontend domain
  • Use environment-specific secrets management

πŸ’‘ Next Steps

  1. Customize AI behavior β†’ Edit backend/app/constants.py (INSTRUCTIONS)
  2. Add your companies β†’ Run backend/prisma/seed.py with your data
  3. Add your transactions β†’ Use database migrations or API endpoints
  4. Create custom widgets β†’ Design in https://widgets.chatkit.studio
  5. Deploy β†’ Follow deployment guide above

About

Starter Repo for OneEthos's 'Building Delightful AI Chat Applications w/ Dynamic UI' Workshop at KnightHacks XIII

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published