Files
basil/CLAUDE.md
2025-10-21 22:04:03 -06:00

6.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Basil is a full-stack recipe manager built with TypeScript. It features a REST API backend, React web frontend, and PostgreSQL database. The application supports importing recipes from URLs via schema.org markup parsing, local/S3 image storage, and comprehensive recipe management (CRUD operations, search, tagging).

Architecture

Monorepo Structure:

  • packages/shared/ - Shared TypeScript types and interfaces used across all packages
  • packages/api/ - Express.js REST API server with Prisma ORM
  • packages/web/ - React + Vite web application
  • Future: packages/mobile/ - React Native mobile apps

Key Technologies:

  • Backend: Node.js, TypeScript, Express, Prisma ORM, PostgreSQL
  • Frontend: React, TypeScript, Vite, React Router
  • Infrastructure: Docker, Docker Compose, nginx
  • Recipe Scraping: Cheerio for HTML parsing, Schema.org Recipe markup support

Database Schema:

  • Recipe - Main recipe entity with metadata (prep/cook time, servings, ratings)
  • Ingredient - Recipe ingredients with amounts, units, and ordering
  • Instruction - Step-by-step instructions with optional images
  • RecipeImage - Multiple images per recipe
  • Tag / RecipeTag - Many-to-many tagging system

Storage Architecture:

  • Primary: Local filesystem storage (./uploads)
  • Optional: S3 storage (configurable via environment variables)
  • Storage service implements strategy pattern for easy switching

Development Commands

# Install all dependencies (root + all packages)
npm install

# Development mode (starts all packages with hot reload)
npm run dev

# Build all packages
npm run build

# Lint all packages
npm run lint

# Docker commands
npm run docker:up      # Start all services (PostgreSQL, API, web)
npm run docker:down    # Stop all services
npm run docker:build   # Rebuild Docker images

Backend-Specific Commands

cd packages/api

# Development with auto-reload
npm run dev

# Database migrations
npm run prisma:migrate       # Create and apply migration
npm run prisma:generate      # Generate Prisma client
npm run prisma:studio        # Open Prisma Studio GUI

# Build for production
npm run build
npm start

Frontend-Specific Commands

cd packages/web

# Development server
npm run dev

# Production build
npm run build
npm run preview    # Preview production build locally

Configuration

Environment Variables (packages/api/.env):

PORT=3001
NODE_ENV=development
DATABASE_URL=postgresql://basil:basil@localhost:5432/basil?schema=public
STORAGE_TYPE=local                    # or 's3'
LOCAL_STORAGE_PATH=./uploads
CORS_ORIGIN=http://localhost:5173

For S3 storage, add:

S3_BUCKET=basil-recipes
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-key
S3_SECRET_ACCESS_KEY=your-secret

Key Features

Recipe Import from URL

  • POST /api/recipes/import - Scrapes recipe from URL using schema.org markup
  • Extracts: title, description, ingredients, instructions, times, images
  • Handles JSON-LD structured data (primary) with fallback to manual parsing
  • Downloads and stores images locally or on S3

Recipe Management

  • Full CRUD operations on recipes
  • Pagination and search (by title, description)
  • Filtering by cuisine, category
  • Image upload with multiple images per recipe
  • Tagging system for organization

Storage Service

  • Abstracted storage interface in packages/api/src/services/storage.service.ts
  • Local storage: Saves to filesystem with timestamped filenames
  • S3 storage: Placeholder for AWS SDK implementation
  • Easy to extend for other storage providers

Adding New Features

Adding a New API Endpoint

  1. Add route handler in packages/api/src/routes/*.routes.ts
  2. Update shared types in packages/shared/src/types.ts if needed
  3. Rebuild shared package: cd packages/shared && npm run build
  4. Use Prisma client for database operations

Adding a New Frontend Page

  1. Create component in packages/web/src/pages/
  2. Add route in packages/web/src/App.tsx
  3. Create API service methods in packages/web/src/services/api.ts
  4. Import and use shared types from @basil/shared

Database Schema Changes

  1. Edit packages/api/prisma/schema.prisma
  2. Run npm run prisma:migrate to create migration
  3. Run npm run prisma:generate to update Prisma client
  4. Update TypeScript types in packages/shared/src/types.ts to match

Docker Deployment

The project includes full Docker support for production deployment:

docker-compose up -d

This starts:

  • PostgreSQL database (port 5432)
  • API server (port 3001)
  • Web frontend served via nginx (port 5173)

Persistent volumes:

  • postgres_data - Database storage
  • uploads_data - Uploaded images

API Reference

Recipes:

  • GET /api/recipes - List all recipes (supports pagination, search, filters)
  • GET /api/recipes/:id - Get single recipe with all relations
  • POST /api/recipes - Create new recipe
  • PUT /api/recipes/:id - Update recipe
  • DELETE /api/recipes/:id - Delete recipe and associated images
  • POST /api/recipes/:id/images - Upload image for recipe
  • POST /api/recipes/import - Import recipe from URL

Query Parameters:

  • page, limit - Pagination
  • search - Search in title/description
  • cuisine, category - Filter by cuisine or category

Important Implementation Details

Prisma Relations

  • All related entities (ingredients, instructions, images, tags) use cascade delete
  • Ingredients and instructions maintain ordering via order and step fields
  • Tags use many-to-many relationship via RecipeTag join table

Recipe Scraping

  • Primary: Parses JSON-LD application/ld+json scripts for Schema.org Recipe data
  • Fallback: Extracts basic info from HTML meta tags and headings
  • Handles ISO 8601 duration format (PT30M, PT1H30M) for cook times
  • Downloads images asynchronously and stores them locally

Frontend Routing

  • Uses React Router v6 for client-side routing
  • Vite proxy forwards /api and /uploads requests to backend during development
  • Production uses nginx reverse proxy to backend API

TypeScript Workspace

  • Root package.json defines npm workspaces
  • Packages can reference each other (e.g., @basil/shared)
  • Must rebuild shared package when types change for other packages to see updates