Project Overview
hh-felidae is a restaurant platform monorepo using Turborepo with a microservices architecture focused on data-driven restaurant recommendations and search.
Applications
- apps/jaguar: Admin dashboard (Nuxt.js + vue-shadcn/ui + TailwindCSS + TanStack Query + urql GraphQL)
- apps/puma: Search service (Fastify + Mercurius GraphQL + OpenSearch + BullMQ + Kafka streaming)
- apps/tiger: Core backend (Fastify + Mercurius GraphQL + Multi-DB Drizzle + BullMQ + AWS Personalize)
- appx/: Infrastructure services (GrowthBook, Kafka connectors, Metarank, OpenSearch)
Workspace Packages
- pkgs/database: Shared database package (@hh-felidae/database) - Drizzle ORM schemas for 3 databases
- pkgs/shared: Shared utilities and types across applications
Development Workflow
Quick Start
# Install dependencies
npm install
# Start specific apps
npm run jaguar # Admin frontend on :3001
npm run puma # Search API on :4000
npm run tiger # Backend API on :4001
Database Architecture (@hh-felidae/database)
Database Structure
- db1: External legacy database (MySQL) - read-only restaurant/user data
- db2: Data warehouse (PostgreSQL) - analytics and ML training data
- db3: Core application database (PostgreSQL) - CMS content, banners, configurations
Database Operations
Package-level Operations (pkgs/database/)
cd pkgs/database
# Generate migrations after schema changes
npm run db2:generate
npm run db3:generate
# Open Drizzle Studio for visual inspection
npm run db1:studio # MySQL legacy data
npm run db2:studio # PostgreSQL warehouse
npm run db3:studio # PostgreSQL core app
Application-level Operations (apps/tiger/)
cd apps/tiger
# Run migrations (Tiger owns migration execution)
npm run db2:migrate
npm run db3:migrate
Migration Strategy
- Tiger owns migrations: Only Tiger runs migration scripts (
apps/tiger/src/scripts/migrate-db*.ts) - db1: No migrations (external read-only database, use
db1:pullto sync schema) - db2/db3: Migrations generated in
pkgs/database, executed by Tiger - Other apps: Import schemas only, no migration execution
Critical Data Flow
- Restaurant Data: db1 → Kafka → puma (OpenSearch indexing) + tiger (ML pipeline)
- User Interactions: frontend → tiger → BullMQ → AWS Personalize + Metarank
- Search: frontend → puma → OpenSearch → ranked results
- Admin Content: jaguar → tiger → db3 (banners, sections, tags)
Architecture Patterns
Backend Services (Fastify + Mercurius)
- Plugin System: All cross-cutting concerns in
src/plugins/(auth, caching, GraphQL, Redis, Kafka) - GraphQL Schema: Centralized in
src/graphql/schema.tswith Mercurius codegen for types - Multi-Database: Separate Drizzle configs per DB (
drizzle-db1/2/3.config.ts) - Queue Architecture: BullMQ workers in
src/services/data-queue/workers/for async processing - Service Layer: Business logic in
src/services/organized by domain (aws-personalize/, opensearch/, etc.)
Frontend (Nuxt + Vue Composition API)
- Data Layer: GraphQL composables in
app/composables/wrapping TanStack Query + urql client - Type Safety: Import types directly from Tiger’s generated GraphQL types
- HTTP Clients: Separate clients for Tiger/Puma GraphQL + REST in
app/libraries/http-client.ts - State Management: TanStack Query for server state, no global state management needed
- File Uploads: Multi-step upload pattern via GraphQL mutations (upload → commit workflow)
Background Job Patterns (BullMQ)
- Queue Separation: Different queues by concern (default, scheduled, interaction, impression)
- Job Organization: Jobs in
src/services/data-queue/jobs/, workers inworkers/ - Data Pipeline: Kafka → Queue → OpenSearch/S3/AWS Personalize
- Scheduled Jobs: RRule-based cron jobs for data sync and ML model training
- Queue Monitoring: Bull Board UI at
/bullmqendpoint
Service Communication
- jaguar ↔ tiger: GraphQL over HTTP with credentials (admin/CMS operations)
- Apps ↔ puma: GraphQL over HTTP (search and restaurant discovery)
- Background Processing: Redis + BullMQ for async data processing pipelines
- Event Streaming: Kafka for real-time data changes (restaurant updates, user events)
- ML Pipeline: Tiger → AWS Personalize for recommendation model training
- Search Index: Tiger/Kafka → Puma → OpenSearch for restaurant search
Development Standards
- TypeScript: Strict mode, shared types via generated GraphQL schemas (
src/graphql/generated.ts) - Database Conventions: snake_case for all DB schemas, separate schema files per domain
- GraphQL Patterns: Mercurius with codegen, input validation via Zod, directive-based auth
- Queue Job Patterns: Idempotent jobs with progress tracking, exponential backoff on failures
- Environment Config: Strict validation via env-schema, separate configs per service
- Error Handling: Rollbar integration for production error tracking
- Language Support: Multi-language content with translation tables and
X-Hh-Languageheaders
Integration Points
- AWS Personalize: Real-time event tracking + batch recommendation generation
- OpenSearch: Restaurant indexing with availability updates and search ranking
- Cloudflare R2: File storage with temporary upload → commit workflow
- Kafka: Event streaming for data pipeline coordination
- Better Auth: Shared authentication system across services
Key Files to Reference
pkgs/database/- Shared database package with schemas, migrations, and utilitiespkgs/database/README.md- Complete database package documentation and usage examplesapps/tiger/src/graphql/schema.ts- Central GraphQL schema with business logic definitionsapps/tiger/src/libraries/database.ts- Full database initialization example (all 3 databases)apps/puma/src/libraries/database.ts- Partial initialization example (db1 only)apps/jaguar/app/composables/use*.ts- Frontend data access patterns with TanStack Queryapps/tiger/src/services/data-queue/workers/- Background job processing patternsapps/puma/src/services/opensearch/- Search indexing and ranking logicturbo.json- Monorepo build dependencies and caching configurationcompose.yaml- Local development infrastructure servicesapps/*/src/config/- Environment configuration and validation schemas
Common Debugging Commands
# Queue monitoring
open http://localhost:4001/bullmq # Tiger queue dashboard
open http://localhost:4000/bullmq # Puma queue dashboard
# Database inspection
cd apps/tiger && npm run db3:studio # Visual database browser
Always consider cross-service impact and data pipeline dependencies when making changes.