Build a Recipe Finder with Search
Build a recipe finder app with full-text search, ingredient filtering, dietary tags, and API integration for a rich cooking experience.
Setting up the recipe data model
A recipe finder combines search, filtering, and rich content display — patterns that apply to any content-heavy application. Start by defining the data model. Ask Claude Code: Create a Next.js project with TypeScript and Tailwind for a recipe finder app. Define types at src/types.ts for: Recipe (id, title, slug, description, image URL, prepTime in minutes, cookTime in minutes, totalTime computed, servings, difficulty as easy or medium or hard, cuisine as string, mealType as breakfast or lunch or dinner or snack or dessert, dietaryTags as array containing options like vegetarian, vegan, gluten-free, dairy-free, nut-free, low-carb, ingredients as array of Ingredient, steps as array of Step, nutrition as NutritionInfo, rating, reviewCount, source attribution), Ingredient (name, amount, unit, optional flag, substitutes as array of strings), Step (number, instruction, duration optional, image optional), and NutritionInfo (calories, protein, carbs, fat, fibre, sugar, all per serving). Create a seed data file at src/data/recipes.ts with 20 sample recipes across different cuisines, difficulties, and dietary categories. Ask Claude Code: Generate 20 realistic recipes with full ingredient lists, step-by-step instructions, and accurate nutrition information. Include a mix of Italian, Asian, Mexican, Indian, and British recipes. Ensure at least 5 are vegetarian, 3 are vegan, and 4 are gluten-free. Each recipe should have 5 to 15 ingredients and 4 to 10 steps. The sample data is your development database. In production, you would connect to a recipe API like Spoonacular or Edamam, but building with local data first lets you focus on the UI and search logic.
Building the search engine
Search is the core feature. Users should find recipes by name, ingredient, cuisine, or any keyword. Ask Claude Code: Create a search engine at src/lib/search.ts. Implement full-text search that matches against the recipe title, description, ingredient names, cuisine, and dietary tags. Rank results by relevance: exact title matches first, then title contains the query, then ingredient matches, then description matches. The search should be case-insensitive and handle partial matches — searching for chick should match both Chicken Tikka and Chickpea Curry. Implement tokenised search: split the query into words and match recipes that contain all words (AND logic). Searching for spicy chicken should find recipes that contain both spicy and chicken, even if the words are not adjacent. Ask Claude Code: Add search highlighting. When displaying results, wrap matching text in a mark element so it is visually highlighted. Show a search results count and the time taken (for example, 12 recipes found in 3ms). Build the search UI. Ask Claude Code: Create a SearchBar component with an input field, a search icon, and a clear button. Show search results as a dropdown below the search bar as the user types (instant search with debounce of 200ms). Each result in the dropdown shows the recipe title, cuisine tag, total time, and difficulty. Pressing Enter navigates to the full search results page. Clicking a result navigates directly to that recipe. Add search suggestions: when the search bar is focused but empty, show popular searches and recent searches (stored in localStorage). Ask Claude Code: Implement recent search history. Store the last 10 unique search queries. Show them when the search bar is focused. Clicking a recent search fills the search bar and executes the search. Add a clear history button. Common error: debouncing search input is essential. Without it, every keystroke triggers a search, which is wasteful and can cause results to flicker as partial queries return different results.
Advanced filtering and faceted navigation
Beyond text search, users want to filter by specific criteria. Ask Claude Code: Create a FilterPanel component shown as a sidebar on desktop and a slide-out drawer on mobile. Include these filters: Meal Type (checkboxes for breakfast, lunch, dinner, snack, dessert), Dietary Tags (checkboxes for vegetarian, vegan, gluten-free, dairy-free, nut-free, low-carb), Difficulty (radio buttons for any, easy, medium, hard), Cuisine (checkboxes for all available cuisines), Total Time (slider or preset buttons: under 15 min, under 30 min, under 60 min, any), and Calories per serving (range slider with min and max). Show the count of matching recipes next to each filter option — Vegetarian (8), Vegan (3). This is called faceted navigation and it helps users understand what is available before clicking. When a filter would return zero results, grey it out. Ask Claude Code: Implement faceted counts for all filter options. After applying the current filters, recalculate the available counts for every other filter option. This prevents users from selecting filter combinations that yield no results. Combine filters with AND logic: selecting Vegetarian and Under 30 min shows only recipes that are both vegetarian and take under 30 minutes. Ask Claude Code: Make all filters reflect in the URL as query parameters so filtered views are shareable and bookmarkable. Selecting vegetarian and dinner should produce a URL like /recipes?dietary=vegetarian&meal=dinner. Loading that URL should pre-select the corresponding filters. Add a sort dropdown. Ask Claude Code: Let users sort results by relevance (default when searching), rating (highest first), total time (quickest first), calories (lowest first), and newest. Show the active sort option clearly. Common error: when combining search and filters, apply search first (to get matching recipes) then filters (to narrow the matches). Applying filters first and then searching within filtered results gives different and usually worse results.
Recipe detail page with interactive features
Each recipe needs a rich detail page that makes cooking easy. Ask Claude Code: Create a recipe detail page at src/app/recipes/[slug]/page.tsx. The layout should include: a hero image at the top with the recipe title overlaid, a metadata bar showing total time, servings, difficulty, cuisine, and dietary tags, a two-column layout on desktop with ingredients on the left and steps on the right, and nutrition information in a compact card. Make the ingredient list interactive. Ask Claude Code: Add a servings adjuster — plus and minus buttons that recalculate ingredient amounts when the user changes the serving count. If the original recipe serves 4 and the user selects 2, all ingredient amounts should halve. Handle fractional amounts gracefully: display 0.5 as 1/2, 0.25 as 1/4, and 0.33 as 1/3. Add checkboxes next to each ingredient so users can tick them off while cooking. Make the steps interactive too. Ask Claude Code: Add a cooking mode that highlights the current step, dims completed steps, and shows a timer button next to any step that mentions a specific duration. Clicking the timer starts a countdown with a notification sound when complete. Add a Print Recipe button. Ask Claude Code: Create a print-optimised stylesheet that shows the recipe in a clean, single-column format suitable for printing. Remove navigation, sidebars, and interactive elements in the print version. Include a QR code linking back to the digital version. Add an ingredients shopping list. Ask Claude Code: Create an Add to Shopping List button that adds the recipe's ingredients to a persistent shopping list stored in localStorage. If an ingredient already exists in the list (from another recipe), combine the amounts. Show the shopping list as a slide-out panel accessible from the navigation bar.
Favourites and meal planning
Turn the recipe finder from a search tool into a personal cooking companion. Ask Claude Code: Add a favourites system. Each recipe card and detail page has a heart icon button. Clicking it toggles the recipe as a favourite, stored in localStorage. Create a Favourites page showing all saved recipes as a grid of cards. Add a filter by cuisine and dietary tag within favourites. Show how many times each recipe has been favourited (simulated with random counts for the seed data). Build a meal planner. Ask Claude Code: Create a weekly meal planner at src/app/meal-plan/page.tsx. Show a 7-day grid (Monday through Sunday) with slots for breakfast, lunch, and dinner. Users drag recipes from a sidebar (showing favourites and recent views) into meal slots. Alternatively, click a slot and search for a recipe to assign. Show the daily calorie total and weekly nutrition summary based on the assigned recipes. Add a Generate Shopping List button that collects all ingredients from the planned meals, combines duplicates, and shows a consolidated shopping list grouped by category (produce, dairy, meat, pantry, spices). Ask Claude Code: Implement automatic ingredient categorisation. Use a lookup table mapping common ingredients to categories: tomatoes map to produce, milk maps to dairy, chicken maps to meat, olive oil maps to pantry, cumin maps to spices. For ingredients not in the lookup table, default to Other. Allow the user to manually recategorise. The meal plan should persist in localStorage and survive page reloads. Add an export option that sends the meal plan and shopping list as a formatted email. Ask Claude Code: Create a Share Meal Plan feature that generates a clean summary of the week's meals with recipe links. Format it for copying to clipboard or sharing via email. Common error: when combining ingredient amounts from multiple recipes, ensure the units match. Two cups of flour plus 500 grams of flour should not be blindly summed — either convert to the same unit or list them separately.
Performance, SEO, and deployment
A recipe site needs excellent SEO — most recipe discovery happens through search engines. Ask Claude Code: Add structured data (JSON-LD) to every recipe page using the Schema.org Recipe type. Include the recipe name, description, image, prep time, cook time, total time, servings, ingredients, steps, nutrition, and aggregated rating. This structured data enables rich results in Google Search — recipe cards with images, ratings, and cooking times directly in search results. Optimise images: recipe images are large and slow to load. Ask Claude Code: Use the Next.js Image component with proper width, height, and alt attributes. Configure image sizes for responsive loading: small thumbnails in search results, medium images in recipe cards, and large images on detail pages. Add blur placeholder loading so images fade in smoothly. Add static generation for recipe pages. Ask Claude Code: Use generateStaticParams to pre-render all recipe pages at build time. This makes every recipe page load instantly since it is served as static HTML. For the search results page, use client-side rendering since the content depends on the search query. Create sitemap.xml and robots.txt. Ask Claude Code: Generate a sitemap listing all recipe pages, the homepage, and the search page. Set appropriate change frequencies — recipe pages are weekly, the homepage is daily. Submit the sitemap to Google Search Console after deployment. Deploy to Vercel with proper configuration. Ask Claude Code: Set up the project for Vercel deployment. Configure caching headers — static recipe pages cached for a day, images cached for a week, search API responses not cached. Test the deployed site with Google's Rich Results Test to verify structured data is valid. Test with Lighthouse to verify performance scores above 90 for performance, accessibility, best practices, and SEO. The recipe finder is complete — a content-rich application with search, filtering, interactivity, and production-ready SEO.
Search and Filtering Patterns
This guide is hands-on and practical. The full curriculum covers the conceptual foundations in depth with structured lessons and quizzes.
Go to lesson