Paul R Kartchner 33a857c456 feat: make nested cookbooks responsive and redesign compact toolbar UI
Nested Cookbooks Fix:
- Added dynamic gridStyle to .cookbooks-grid in CookbookDetail.tsx
- Removed hardcoded 5-column grid from CSS, now respects column selector
- Nested cookbooks now respond to column count changes (3, 5, 7, 9)

Toolbar UI Redesign (CookbookDetail.css & Cookbooks.css):
- Reduced toolbar padding from 1.5rem to 0.75rem 1rem
- Changed alignment from flex-end to center for cleaner layout
- Made buttons more compact:
  - Reduced padding to 0.35rem 0.6rem (was 0.5rem 0.75rem)
  - Reduced font size to 0.8rem (was 0.9rem)
  - Reduced min-width to 2rem (was 2.5rem)
- Grouped buttons with subtle border styling instead of individual borders
- Reduced gaps between controls from 2rem/1.5rem to 1.5rem/1rem
- Made labels smaller and lighter weight (0.8rem, 500 weight)
- Updated page navigation with lighter borders and subtle hover states
- Changed colors to more subtle grays (#d0d0d0, #555) instead of bold green
- Reduced box-shadow for subtler appearance
- Added 1px border for better definition

Result: Consistent, compact, user-friendly controls across all recipe
and cookbook list pages.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 08:53:16 -07:00

Basil 🌿

A modern, full-stack recipe manager with web and mobile support. Import recipes from any URL, manage your recipe collection, and access them from anywhere.

Features

  • Recipe Import: Automatically import recipes from URLs using schema.org markup
    • Add tags during import for instant organization
    • Works with 600+ supported recipe sites plus any site with schema.org markup
    • Preview recipe before saving with immediate tag management
  • Full Recipe Management: Create, read, update, and delete recipes
  • Rich Recipe Data: Store ingredients, instructions, prep/cook times, servings, images, and more
  • Tag Organization: Quick tagging system with autocomplete for rapid recipe organization
    • Add/remove tags inline on recipe detail view
    • Tag recipes during import
    • Filter recipes by tags
  • Recipe Scaling: Adjust serving sizes with automatic ingredient scaling
  • Cookbooks: Organize recipes into collections with auto-filtering by tags and categories
  • Search & Filter: Find recipes by title, cuisine, category, or tags
  • Multiple Images: Add multiple images to each recipe
  • User Authentication: Secure multi-user support with email/password and OAuth
  • Backup & Restore: Complete data backup including recipes, cookbooks, and images
  • Flexible Storage: Local filesystem storage by default, optional S3 support
  • Docker Support: Easy deployment with Docker Compose
  • API-First Design: RESTful API for web and future mobile apps

Tech Stack

  • Backend: Node.js, TypeScript, Express, Prisma ORM, PostgreSQL
  • Frontend: React, TypeScript, Vite, React Router
  • Infrastructure: Docker, Docker Compose, nginx
  • Monorepo: npm workspaces with shared types

Quick Start

Prerequisites

  • Node.js 20+
  • PostgreSQL 16+ (or use Docker)
  • Python 3.x with pip (for recipe scraper)
  • Docker (optional, for containerized deployment)

Python Dependencies: The recipe import feature requires Python 3 and the recipe-scrapers package:

pip3 install recipe-scrapers

For Docker deployments, Python dependencies are automatically installed in the container.

Development Setup

  1. Clone the repository

    git clone <repository-url>
    cd basil
    
  2. Install dependencies

    npm install
    
  3. Set up environment variables

    cp packages/api/.env.example packages/api/.env
    # Edit packages/api/.env with your database credentials
    
  4. Start PostgreSQL (if not using Docker)

    # Create a database named 'basil'
    createdb basil
    
  5. Run database migrations

    cd packages/api
    npm run prisma:migrate
    npm run prisma:generate
    cd ../..
    
  6. Start development servers

    npm run dev
    

    This starts:

Docker Deployment

For production or easy local setup:

# Start all services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop services
docker-compose down

Services will be available at:

Project Structure

basil/
├── packages/
│   ├── api/          # Backend API server
│   │   ├── prisma/   # Database schema and migrations
│   │   └── src/      # Express routes, services, config
│   ├── web/          # React web application
│   │   └── src/      # Components, pages, services
│   └── shared/       # Shared TypeScript types
├── docker-compose.yml
└── package.json      # Workspace root

Usage

Importing a Recipe

  1. Navigate to "Import Recipe" in the web app
  2. Paste a recipe URL (supports 600+ sites including AllRecipes, Food Network, King Arthur Baking, etc.)
  3. Click "Import Recipe" to fetch and parse the recipe
  4. Preview the imported recipe details
  5. Add tags using the quick tag input at the top (with autocomplete)
  6. Press Enter after each tag for rapid multi-tag addition
  7. Save to your collection

The recipe importer works with any website that uses schema.org Recipe markup, even if not officially supported by recipe-scrapers.

Managing Tags

Quick Tag Management:

  • On recipe detail pages, use the inline tag input next to the servings adjuster
  • Press Enter after typing each tag for rapid multi-tag addition
  • Focus stays in the input field for quick consecutive tagging
  • Autocomplete suggests existing tags as you type
  • Click the × button on any tag to remove it

Tag-based Organization:

  • Filter recipe list by tag name
  • Use tags to organize recipes by cuisine, meal type, dietary restrictions, etc.
  • Tags are automatically created when first used
  • Rename or delete unused tags from the Tags page

API Examples

Import recipe from URL:

curl -X POST http://localhost:3001/api/recipes/import \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/recipe"}'

Get all recipes:

curl http://localhost:3001/api/recipes

Create a recipe:

curl -X POST http://localhost:3001/api/recipes \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Chocolate Chip Cookies",
    "ingredients": [
      {"name": "flour", "amount": "2", "unit": "cups", "order": 0}
    ],
    "instructions": [
      {"step": 1, "text": "Preheat oven to 350°F"}
    ],
    "tags": ["dessert", "cookies", "quick"]
  }'

Update recipe tags:

curl -X PUT http://localhost:3001/api/recipes/:id \
  -H "Content-Type: application/json" \
  -d '{
    "tags": ["italian", "dinner", "vegetarian"]
  }'

Filter recipes by tag:

curl http://localhost:3001/api/recipes?tag=dessert

Testing

Basil includes comprehensive test coverage with unit and integration tests:

# Run all tests
npm test

# Run tests with coverage report
cd packages/api
npm run test -- --coverage

# Run specific test file
npx vitest run src/routes/recipes.routes.test.ts

Test Coverage

  • Overall: 77.6% coverage
  • Routes: 84% coverage
    • recipes.routes.ts: 87%
    • tags.routes.ts: 92%
    • cookbooks.routes.ts: 88%
    • backup.routes.ts: 74%
    • auth.routes.ts: 37%
  • Services: 66% coverage
  • Utils: 100% coverage

Test suite includes:

  • 377+ passing tests across 21 test files
  • Unit tests for all route handlers
  • Integration tests for API endpoints
  • Real integration tests for recipe scraper (live URL testing)
  • Authentication and authorization tests
  • Backup and restore functionality tests

Configuration

Storage Options

Local Storage (Default):

STORAGE_TYPE=local
LOCAL_STORAGE_PATH=./uploads

S3 Storage:

STORAGE_TYPE=s3
S3_BUCKET=your-bucket-name
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key

Database

Default PostgreSQL connection:

DATABASE_URL=postgresql://basil:basil@localhost:5432/basil?schema=public

For external database services (AWS RDS, DigitalOcean, etc.), update the connection string.

Development

Commands

# Install dependencies
npm install

# Start all services in development mode
npm run dev

# Build all packages
npm run build

# Lint all packages
npm run lint

# Docker commands
npm run docker:up
npm run docker:down
npm run docker:build

Database Migrations

cd packages/api

# Create a new migration
npm run prisma:migrate

# Generate Prisma client
npm run prisma:generate

# Open Prisma Studio (GUI for database)
npm run prisma:studio

Future Enhancements

  • Mobile apps (React Native for iOS and Android)
  • Recipe sharing and social features
  • Meal planning and grocery lists
  • Nutritional information calculation
  • Print-friendly recipe view with custom formatting
  • Recipe ratings and reviews
  • Shopping list generation from recipes
  • Ingredient substitution suggestions
  • Recipe notes and personal modifications
  • Advanced search with multiple filters
  • Recipe version history

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

When contributing:

  1. Write tests for new features (maintain 80%+ coverage)
  2. Follow existing code style and conventions
  3. Update documentation as needed
  4. Ensure all tests pass before submitting PR
Description
Basil is my recipe tracker
Readme 1.5 MiB
2026-01-20 04:38:55 +00:00
Languages
TypeScript 82.6%
CSS 11.8%
Shell 4.1%
JavaScript 0.9%
Python 0.4%
Other 0.2%