Please bookmark this page to avoid losing your image tool!

Image Recipe Collection

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, recipeTitle = "Delicious Recipe", ingredients = "1 cup Love\n2 tbsp Patience\n1 pinch of Genius\nA dash of Creativity", instructions = "1. Combine all ingredients in a bowl.\n2. Mix with passion and care.\n3. Bake in the oven of your heart.\n4. Share with friends and family and enjoy the delicious results!", servings = "4-6 people", prepTime = "30 minutes") {

    // Helper function to load Google Fonts once
    const loadFonts = async () => {
        const fontId = 'google-fonts-image-recipe-card';
        // Check if fonts are already loaded or the style tag exists
        if (window.recipeCardFontsLoaded || document.getElementById(fontId)) {
            window.recipeCardFontsLoaded = true;
            return;
        }

        const link = document.createElement('link');
        link.id = fontId;
        link.rel = 'stylesheet';
        link.href = 'https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,700&family=Montserrat:wght@400;600&display=swap';
        document.head.appendChild(link);

        try {
            await document.fonts.load('700 12px Lora');
            await document.fonts.load('400 12px Montserrat');
            window.recipeCardFontsLoaded = true;
        } catch (e) {
            console.error("Font loading failed:", e);
            // Continue anyway, browser might use fallback fonts
        }
    };

    await loadFonts();

    // Setup a temporary canvas with a large height to draw on
    const tempCanvas = document.createElement('canvas');
    const ctx = tempCanvas.getContext('2d');

    // Define layout constants for our recipe card design
    const cardWidth = 800;
    const padding = 50;
    const contentWidth = cardWidth - 2 * padding;
    const titleFont = '700 48px Lora';
    const headingFont = '600 24px Montserrat';
    const bodyFont = '400 20px Montserrat';
    const detailsFont = '400 18px Montserrat';
    const primaryColor = '#2d2d2d';
    const secondaryColor = '#555555';
    const backgroundColor = '#FDFBF5';
    const bodyLineHeight = 32;
    const titleLineHeight = 60;
    const sectionSpacing = 40;
    const itemSpacing = 20;

    tempCanvas.width = cardWidth;
    tempCanvas.height = 8000; // Large enough for any reasonable recipe

    // Helper to wrap and draw text, returns the Y position after drawing
    const wrapAndDrawText = (text, x, y, maxWidth, font, color, lineHeight) => {
        ctx.font = font;
        ctx.fillStyle = color;
        ctx.textBaseline = 'top';

        const lines = text.split('\n');
        let currentY = y;

        for (const line of lines) {
            const words = line.trim().split(' ');
            let currentLine = '';

            for (let i = 0; i < words.length; i++) {
                const testLine = currentLine + words[i] + ' ';
                const metrics = ctx.measureText(testLine);
                if (metrics.width > maxWidth && i > 0) {
                    ctx.fillText(currentLine.trim(), x, currentY);
                    currentLine = words[i] + ' ';
                    currentY += lineHeight;
                } else {
                    currentLine = testLine;
                }
            }
            if (currentLine.trim() !== '') {
                ctx.fillText(currentLine.trim(), x, currentY);
                currentY += lineHeight;
            }
        }
        return currentY;
    };

    let currentY = 0;

    // 1. Draw Background
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);

    // 2. Draw Image at the top
    const imgHeight = (originalImg.height / originalImg.width) * cardWidth;
    ctx.drawImage(originalImg, 0, 0, cardWidth, imgHeight);
    currentY = imgHeight;

    const contentX = padding;

    // 3. Draw Recipe Title
    currentY += sectionSpacing;
    currentY = wrapAndDrawText(recipeTitle, contentX, currentY, contentWidth, titleFont, primaryColor, titleLineHeight);

    // 4. Draw Details (Servings & Prep Time)
    currentY += itemSpacing;
    ctx.font = detailsFont;
    ctx.fillStyle = secondaryColor;
    ctx.textBaseline = 'top';
    const detailsText = `Servings: ${servings}   |   Prep Time: ${prepTime}`;
    ctx.fillText(detailsText, contentX, currentY);
    currentY += 25; // Approximate height for the details line

    // 5. Draw a decorative separator line
    currentY += itemSpacing;
    ctx.beginPath();
    ctx.moveTo(contentX, currentY);
    ctx.lineTo(contentX + contentWidth, currentY);
    ctx.strokeStyle = '#D8C8B8';
    ctx.lineWidth = 1;
    ctx.stroke();
    currentY += sectionSpacing;

    // 6. Draw Ingredients section
    ctx.font = headingFont;
    ctx.fillStyle = primaryColor;
    ctx.textBaseline = 'top';
    ctx.fillText("Ingredients", contentX, currentY);
    currentY += 35; // Space after heading
    currentY = wrapAndDrawText(ingredients, contentX, currentY, contentWidth, bodyFont, primaryColor, bodyLineHeight);

    currentY += sectionSpacing;

    // 7. Draw Instructions section
    ctx.font = headingFont;
    ctx.fillStyle = primaryColor;
    ctx.textBaseline = 'top';
    ctx.fillText("Instructions", contentX, currentY);
    currentY += 35; // Space after heading
    currentY = wrapAndDrawText(instructions, contentX, currentY, contentWidth, bodyFont, primaryColor, bodyLineHeight);

    // 8. Create the final, correctly sized canvas
    const finalHeight = currentY + padding;
    const finalCanvas = document.createElement('canvas');
    finalCanvas.width = cardWidth;
    finalCanvas.height = finalHeight;
    const finalCtx = finalCanvas.getContext('2d');

    // 9. Copy the rendered content from the temporary canvas to the final canvas
    finalCtx.drawImage(tempCanvas, 0, 0, cardWidth, finalHeight, 0, 0, cardWidth, finalHeight);

    return finalCanvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Image Recipe Collection tool allows users to create visually appealing recipe cards by combining an image with textual recipe details. Users can input a recipe title, ingredients, instructions, serving size, and prep time, which are then artistically laid out on a digital card. This tool is useful for home cooks, food bloggers, and anyone looking to share their recipes in an attractive format, making it ideal for social media posts, blogs, or personal collections.

Leave a Reply

Your email address will not be published. Required fields are marked *