Skip to content

Conversation

@pansar1
Copy link
Contributor

@pansar1 pansar1 commented Dec 16, 2025

Summary

This PR represents a complete modernization of DevoLunch, introducing AI-powered menu scraping, real-time communication capabilities, and a significantly improved development experience. The changes transform the application from a traditional web scraper to an intelligent, AI-driven system that adapts to website changes automatically.

🤖 AI-First Scraping Architecture

  • Intelligent Menu Extraction: Replaced brittle DOM parsing with Claude AI-powered extraction that understands menu content contextually
  • Self-Healing: AI adapts to website changes without requiring code updates
  • Automatic Dish Classification: AI determines dish types (meat/fish/veg/vegan) without keyword lists
  • Confidence Scoring: Each extraction includes reliability metrics
  • PDF Support: Enhanced PDF text extraction with hallucination prevention
  • Unified Restaurant Configuration: Simplified restaurant setup requiring only metadata (URL, coordinates, title)

🔌 MCP (Model Context Protocol) Integration

  • New MCP Server Package (packages/mcp-server/): Exposes DevoLunch data via MCP protocol
    • get_restaurants: Returns current scrape data
    • search_dishes: Searches dishes across all restaurants
    • suggest_meal: AI-powered meal suggestions with reasoning
  • Browser Automation: WebSocket-based MCP Chrome client for interactive scraping
  • OpenAI Integration: Optional OpenAI support for enhanced query expansion

🎨 Frontend Improvements

  • New Components:

    • PromptPanel: Interactive AI conversation interface
    • MenuModal: Enhanced menu viewing experience
    • SearchInput: Improved search with suggestions
    • SuggestionList: AI-powered meal suggestions
    • ErrorBoundary: Comprehensive error handling
    • McpStatus: Real-time MCP connection status
    • ConversationArea: Chat-like interface for AI interactions
  • Multi-Location Support: Restaurants with multiple locations now properly supported with individual coordinates and maps

  • WebSocket Communication: Real-time updates between client and server

  • Better Error Handling: Component-level error boundaries with recovery

🏗️ Development Environment Modernization

  • Testing Migration: Replaced Jest with Vitest for faster, more modern testing

    • Native ESM support
    • TypeScript without transpilation
    • Better DX with inline snapshots
    • Component error boundary tests added
  • ESLint Upgrade: Migrated to ESLint flat config (v9+)

    • Individual package configurations
    • Removed legacy .eslintrc.json files
    • Modern import resolution
  • Logging Improvements:

    • Unified logger across packages (@devolunch/shared)
    • Browser-safe logging with fallbacks
    • Pino-pretty for beautiful development logs
    • Structured logging in production
  • TypeScript Enhancements:

    • Consolidated TypeScript configurations
    • Base config shared across packages
    • Better type definitions for external dependencies
    • Removed deprecated tsconfig package in favor of root config
  • Build System:

    • Improved Turbo configuration
    • Better caching and dependency management
    • Parallel builds for faster CI/CD

📚 Documentation Overhaul

  • New Documentation Structure (docs/):

    • architecture.md: System architecture overview
    • development.md: Development workflows and guidelines
    • infra.md: Infrastructure and deployment
    • DEPENDENCY_MANAGEMENT.md: Renovate configuration and automated updates
  • Improved README: Better organized with links to detailed docs

  • Scraper Documentation: Comprehensive guide for AI-powered scraping

  • Contributing Guide: Moved to .github/CONTRIBUTING.md with better instructions

🔧 Infrastructure & DevOps

  • Renovate Integration: Automated dependency management

    • Weekly updates every Monday
    • Auto-merge for safe updates (patch/minor dev deps)
    • Grouped updates for related packages
    • Security-first approach with immediate vulnerability updates
  • GitHub Workflows:

    • Dependency review action
    • Improved install-and-test workflow
    • Better caching and performance
  • Git Hooks:

    • Pre-commit: Linting and formatting
    • Commit-msg: Conventional commit validation
    • Pre-push: Test execution
  • Editor Configuration: Added .editorconfig for consistent code style

🗄️ Backend Enhancements

  • New API Routes:

    • /api/v1/ai: AI interaction endpoints
    • WebSocket gateway for real-time communication
  • MCP Client Service: Server-side MCP client for browser automation

  • Storage Service Improvements: Better error handling and retry logic

  • Environment Configuration: Cleaner .env handling

🔄 Refactoring & Code Quality

  • Scraper Refactoring:

    • Separated concerns: content scrapers, dish extractors, AI services
    • Removed 15+ individual restaurant scrapers in favor of unified AI approach
    • Removed legacy keyword-based dish classification (meats, fishes, vegan lists)
    • Better content cleaning and closure detection
  • Shared Packages:

    • Food lexicon (English/Swedish) for better translations
    • Cross-platform logger (Node.js/Browser)
    • Unified types and utilities
  • Removed Deprecated Code:

    • Legacy image resizer (Sharp)
    • Old dish type lookup system
    • Redundant TypeScript configurations
    • Individual ESLint packages

📦 Package Management

  • pnpm Workspaces: Proper monorepo with workspace protocol
  • Dependency Updates: Major version bumps for key dependencies
    • React 18
    • TypeScript 5.8+
    • Node.js 22+
    • Vite 6+
    • Vitest for testing

🎯 Restaurant Coverage

Maintained and improved coverage for 20+ Malmö restaurants with simplified configuration:

  • Hyllie Bistro, Benne Pastabar (multi-location), Bistro Royal
  • Kontrast Västra Hamnen, Lokal 17, MiaMarias
  • Niagara, Quanbyquan, Saltimporten
  • And many more...

Each restaurant now only requires metadata - AI handles the rest!

🧹 Breaking Changes

  • Removed individual restaurant scraper files (replaced with unified system)
  • Removed packages/eslint (use root config)
  • Removed packages/tsconfig (use root config)
  • Migration from Jest to Vitest requires test updates
  • ESLint flat config requires newer Node.js versions

Technical Highlights

  • Lines Changed: 171 files, +15,594 insertions, -9,546 deletions
  • New Packages: MCP server, consolidated shared utilities
  • Test Coverage: Component tests, AI extraction validation
  • Performance: Parallel builds, better caching, WebSocket real-time updates
  • Type Safety: Improved TypeScript configurations and type definitions

Migration Path

For developers working on this codebase:

  1. Install Dependencies: Run pnpm install (enforced by preinstall script)
  2. Review New Docs: Check docs/ folder for architecture and development guides
  3. AI Scraping: New restaurants only need metadata configuration
  4. Testing: Use pnpm test (Vitest) instead of Jest
  5. Logging: Import logger from @devolunch/shared

Future Work

⚠️ IMPORTANT: Known Limitations

Future developers will need to address:

  1. 🔌 AI API Integration: The AI scraping system requires connection to an AI service (Claude API or similar) for dish extraction. The infrastructure is in place but needs:

    • API key configuration
    • Rate limiting implementation
    • Cost monitoring
    • Fallback strategies for API failures
  2. 💬 Slack Integration: The Slack notification service needs updates to work with the new data structure:

    • Multi-location restaurant support
    • AI confidence score display
    • Enhanced formatting for AI-extracted menus
    • WebSocket integration for real-time notifications

These integrations are required for full production functionality.


🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

pansar1 and others added 20 commits September 18, 2025 10:44
- Fix progressive image blur logic to show crisp images when no low-quality version exists
- Consolidate DEVOTEAM_LOCATION coordinates to single source of truth
- Update restaurant sorting to prioritize distance over dish count with alphabetical tiebreaker
- Strengthen AI menu extraction boundaries to prevent bar section inclusion
- Add priority-based extraction rules for "Veckans" weekly specials
- Enhance extraction prompt with hard stop rules for better section filtering
- Fix TypeScript import extensions and boolean type coercion

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add explicit anti-hallucination rules to prevent AI from adding common dishes like Caesar salad or Moo Tod that don't exist on menus
- Remove problematic examples from extraction prompts that were causing false suggestions
- Set temperature to 0.0 for maximum determinism and reduced creativity
- Add PDF text cleaning function to fix common OCR errors (0läsk -> fläsk, con0iterad -> confiterad)
- Update system prompts to emphasize extracting only dishes that actually appear in content
- Clean up tsconfig files across packages for better module resolution
- Simplify geolocation handling in Sort component with graceful fallbacks
- Remove file extensions from server imports for cleaner code

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update all major dependencies to latest versions (Vite 7, Vitest 3, TypeScript 5.7)
- Fix SVG imports for vite-plugin-svgr v4 compatibility (?react syntax)
- Replace deprecated Puppeteer waitForTimeout with Promise-based approach
- Update server module resolution for ESM compatibility with tsx
- Fix ESLint configuration to ignore Puppeteer cache files
- Resolve all dependency security vulnerabilities
- Add proper TypeScript declarations for SVG React components

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add .editorconfig for consistent coding standards across IDEs
- Add .nvmrc to pin Node.js 22.14.0 for team consistency
- Update Docker to Node.js 22 LTS and pnpm 10 for performance
- Enhance .dockerignore with modern exclusion patterns
- Add engine requirements (Node.js >=22, pnpm >=10) to package.json
- Upgrade Vitest configuration with coverage reporting and v8 provider
- Add comprehensive testing dependencies (@testing-library, jsdom)
- Create test setup file with automated cleanup
- Modernize GitHub Actions to latest versions (checkout@v4, setup-node@v4, pnpm@v4)
- Add coverage reporting and security audit to CI pipeline
- Update Turbo configuration for better test caching

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Changes moduleResolution from "node" to "bundler" to match base config
- Adds setTimeout and clearTimeout to browser globals in ESLint config

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
…upport

Improved the notify-slack function with better formatting, threading support, and comprehensive restaurant coverage including multi-location venues.

Key improvements:
- Implemented threaded messaging to reduce message size (8 restaurants per thread)
- Added support for multi-location restaurants (now shows all 39 restaurants)
- Enhanced markdown formatting with proper Slack syntax
- Added visual hierarchy with dish type emojis (🥩🐟🥗🌱)
- Fixed clickable link formatting for malmolunch.se
- Improved TypeScript configuration for ESNext modules
- Removed external dependency on @devolunch/shared package
- Added rate limiting protection between API calls

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Removed unused getTodayNiceFormat function
- Fixed setTimeout reference using globalThis for Node.js compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
The TypeScript build outputs to dist/apps/functions/scraper/src/ directory,
so update the scrape script to use the correct path.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added a 'dev' script to the scraper that pipes output through pino-pretty
for better readability during development, replacing raw JSON logs with
formatted, human-readable output.

Changes:
- Added 'dev' script to scraper package.json with pino-pretty formatting
- Updated root 'scrape:dev' command to use the new dev script
- Maintains structured JSON logging for production while improving DX

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Extract PromptPanel (1100+ lines) into 5 focused components:
  * ConversationArea: message display and rendering
  * MenuModal: restaurant menu popup with card-style design
  * ScrollToSection: navigation chevron component
  * SearchInput: search field with validation
  * SuggestionList: AI recommendation cards

- Improve MenuModal design:
  * Restaurant name in header opposite close button
  * Distance and opening times below name
  * Website/Directions links under name
  * Dishes styled like restaurant cards with dots and borders
  * Better space utilization and left-aligned text

- Remove auto-scrolling behavior from conversation results
- Add missing DOM types to ESLint config
- Move scroll-to-section out of PromptPanel for better separation

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants