diff --git a/.env.example b/.env.example
index 74136cad1..867e372de 100644
--- a/.env.example
+++ b/.env.example
@@ -12,6 +12,8 @@ REACT_APP_ACTIVITY_ID=hackrplay
REACT_APP_DADJOKES_URL=https://jokeapi-v2.p.rapidapi.com/joke/
REACT_APP_DADJOKES_APIKEY=your_rapidapi_key_here
REACT_APP_DADJOKES_APIHOST='jokeapi-v2.p.rapidapi.com'
+REACT_APP_APP_EDAMAM_KEY=your_edamam_api_key
+REACT_APP_APP_EDAMAM_ID=your_edamam_app_id
# Add your API keys below:
# REACT_APP_SEARCH_APIKEY=your_search_api_key
diff --git a/src/plays/pantry-alchemy/IngredientSearch.js b/src/plays/pantry-alchemy/IngredientSearch.js
new file mode 100644
index 000000000..e8f9dd88a
--- /dev/null
+++ b/src/plays/pantry-alchemy/IngredientSearch.js
@@ -0,0 +1,248 @@
+import { useEffect, useState } from 'react';
+import { Autocomplete, TextField, Chip, CircularProgress, Box, Stack, Button } from '@mui/material';
+import SearchIcon from '@mui/icons-material/Search';
+import RecipeSlider from './RecipeSlider';
+
+export default function IngredientAutocomplete({ onSubmit }) {
+ const [options, setOptions] = useState([]);
+ const [value, setValue] = useState([]);
+ const [inputValue, setInputValue] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [recipeLoading, setRecipeLoading] = useState(false);
+ const [recipes, setRecipes] = useState([]);
+ const appId = process.env.REACT_APP_APP_EDAMAM_ID;
+ const appKey = process.env.REACT_APP_APP_EDAMAM_KEY;
+
+ async function searchRecipe(ingredientsArray) {
+ // Join array of ingredients: ['chicken', 'garlic', 'spinach'] -> "chicken garlic spinach"
+ const searchQuery = ingredientsArray
+ .map((item) => (item.includes(' ') ? `"${item}"` : item))
+ .join(' ');
+
+ const params = new URLSearchParams({
+ type: 'public',
+ q: searchQuery,
+ app_id: appId,
+ app_key: appKey
+ });
+
+ const url = `https://api.edamam.com/api/recipes/v2?${params.toString()}`;
+
+ try {
+ setRecipeLoading(true);
+ const response = await fetch(url);
+ const data = await response.json();
+ setRecipes(data.hits);
+ } catch (error) {
+ console.error('Error:', error);
+ } finally {
+ setRecipeLoading(false);
+ }
+ }
+
+ async function searchIngredients(query) {
+ if (!query.trim()) return [];
+
+ const url =
+ `https://world.openfoodfacts.org/api/v3/taxonomy_suggestions` +
+ `?tagtype=ingredients` +
+ `&lc=en` +
+ `&string=${encodeURIComponent(query)}` +
+ `&limit=10`;
+
+ const response = await fetch(url);
+ const data = await response.json();
+
+ return data.suggestions || [];
+ }
+ useEffect(() => {
+ const query = inputValue.trim();
+
+ // Don't search for very short queries
+ if (query.length < 2) {
+ setOptions([]);
+
+ return;
+ }
+
+ const timeout = setTimeout(async () => {
+ try {
+ setLoading(true);
+
+ const data = await searchIngredients(query);
+
+ setOptions(data.map((item) => ({ id: item, label: item })));
+ } catch (error) {
+ console.error('Failed to search ingredients:', error);
+ setOptions([]);
+ } finally {
+ setLoading(false);
+ }
+ }, 400); // debounce
+
+ return () => clearTimeout(timeout);
+ }, [inputValue]);
+
+ return (
+
+
+
+ option.label || ''}
+ inputValue={inputValue}
+ isOptionEqualToValue={(option, value) => option.id === value.id}
+ loading={loading}
+ loadingText="Searching..."
+ noOptionsText={inputValue.length < 2 ? 'Search Ingredients' : 'No ingredients found'}
+ options={options}
+ renderInput={(params) => (
+
+ {loading && }
+ {params.InputProps.endAdornment}
+ >
+ )
+ }
+ }}
+ sx={{
+ '& .MuiAutocomplete-input': {
+ border: 'none !important'
+ },
+ '& .MuiOutlinedInput-root': {
+ minHeight: 56,
+ borderRadius: '14px',
+ backgroundColor: '#fff',
+ border: 'none',
+ // Remove black/default border
+ '& fieldset': {
+ border: '1px solid #E0E0E0'
+ },
+
+ '&:hover fieldset': {
+ border: '1px solid #BDBDBD'
+ },
+
+ '&.Mui-focused fieldset': {
+ border: '2px solid #4CAF50'
+ },
+
+ // Remove black focus outline
+ '&.Mui-focused': {
+ outline: 'none',
+ boxShadow: '0 0 0 3px rgba(76, 175, 80, 0.12)'
+ }
+ },
+
+ '& .MuiInputBase-input': {
+ outline: 'none !important',
+ boxShadow: 'none !important'
+ }
+ }}
+ />
+ )}
+ renderTags={(selected, getTagProps) =>
+ selected.map((option, index) => (
+
+ ))
+ }
+ slotProps={{
+ paper: {
+ sx: {
+ mt: 1,
+ borderRadius: '14px',
+ boxShadow: '0 8px 30px rgba(0, 0, 0, 0.10)',
+ overflow: 'hidden'
+ }
+ },
+ listbox: {
+ sx: {
+ p: '6px',
+
+ '& .MuiAutocomplete-option': {
+ borderRadius: '9px',
+ padding: '10px 12px',
+ marginBottom: '2px',
+
+ '&:hover': {
+ backgroundColor: '#F1F8F2'
+ },
+
+ "&[aria-selected='true']": {
+ backgroundColor: '#E8F5E9',
+ color: '#2E7D32'
+ }
+ }
+ }
+ }
+ }}
+ value={value}
+ onChange={(_, newValue) => {
+ setValue(newValue);
+ }}
+ onInputChange={(_, newInputValue) => {
+ setInputValue(newInputValue);
+ }}
+ />
+ }
+ sx={{
+ width: '6rem',
+ borderRadius: '9px',
+
+ textTransform: 'none',
+ fontSize: '0.78rem',
+ fontWeight: 700,
+
+ backgroundColor: '#2E7D32',
+ boxShadow: 'none',
+
+ '&:hover': {
+ backgroundColor: '#1B5E20',
+ boxShadow: 'none'
+ }
+ }}
+ variant="contained"
+ onClick={() => {
+ searchRecipe(value.map((v) => v.id));
+ }}
+ >
+ {recipeLoading ? : 'Search'}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/plays/pantry-alchemy/PantryAlchemy.js b/src/plays/pantry-alchemy/PantryAlchemy.js
new file mode 100644
index 000000000..24b2d7818
--- /dev/null
+++ b/src/plays/pantry-alchemy/PantryAlchemy.js
@@ -0,0 +1,70 @@
+import PlayHeader from 'common/playlists/PlayHeader';
+import './styles.css';
+import { Stack, Typography } from '@mui/material';
+import IngredientSearch from './IngredientSearch';
+
+// WARNING: Do not change the entry componenet name
+function PantryAlchemy(props) {
+ // Example usage: Search for recipes with chicken, garlic, and sweet potato
+ // searchByIngredients(['chicken', 'garlic', 'sweet potato']);
+ // Your Code Start below.
+
+ return (
+ <>
+
+
+
+ {/* Your Code Starts Here */}
+
+
+
+
+ Pantry Alchemy
+
+
+
+ Turn the ingredients in your pantry into something delicious.
+
+
+
+
+
+
+ {/* Your Code Ends Here */}
+
+
+ >
+ );
+}
+
+export default PantryAlchemy;
diff --git a/src/plays/pantry-alchemy/Readme.md b/src/plays/pantry-alchemy/Readme.md
new file mode 100644
index 000000000..cd13ab990
--- /dev/null
+++ b/src/plays/pantry-alchemy/Readme.md
@@ -0,0 +1,36 @@
+# Pantry Alchemy
+
+An intelligent culinary engine that transforms everyday ingredients into tailored, restaurant-quality dish concepts.
+
+## Play Demographic
+
+- Language: js
+- Level: Beginner
+
+## Creator Information
+
+- User: Farhaan
+- Gihub Link: https://github.com/Farhaan
+- Blog:
+- Video:
+
+## Implementation Details
+
+- React 18 application built with **Material UI**, React Hooks, and the browser `fetch` API.
+- Ingredient autocomplete uses **Open Food Facts**, with 400ms debounced searches and multi-selection.
+- Selected ingredients are submitted to the **Edamam Recipe API** to retrieve matching recipes.
+- Recipes are displayed in responsive horizontal cards with images, ingredient summaries, expandable health labels, and source links.
+
+## Consideration
+
+- Edamam API credentials are currently hardcoded; move them to environment variables or a backend before production.
+- API failures are currently logged to the console rather than displayed to users.
+- `sample.json` contains potentially expiring Edamam image URLs and exposed API credentials.
+- The application depends on external API availability and browser CORS permissions.
+
+## Resources
+
+- **Edamam Recipe API** — recipe search and recipe data.
+- **Open Food Facts** — ingredient autocomplete and taxonomy suggestions.
+- **Material UI** — UI components, responsive styling, cards, chips, and controls.
+- **React** — component architecture, state management, effects, and API interactions.
diff --git a/src/plays/pantry-alchemy/RecipeSlider.js b/src/plays/pantry-alchemy/RecipeSlider.js
new file mode 100644
index 000000000..59a8a6a9c
--- /dev/null
+++ b/src/plays/pantry-alchemy/RecipeSlider.js
@@ -0,0 +1,285 @@
+import { useState } from 'react';
+import {
+ Box,
+ Card,
+ CardContent,
+ CardMedia,
+ Chip,
+ Collapse,
+ IconButton,
+ Typography,
+ Button,
+ Stack
+} from '@mui/material';
+import { ExpandMore, ArrowForward, FavoriteBorder } from '@mui/icons-material';
+
+const chipColors = [
+ { bg: '#E8F5E9', color: '#2E7D32' },
+ { bg: '#E3F2FD', color: '#1565C0' },
+ { bg: '#FFF3E0', color: '#E65100' },
+ { bg: '#F3E5F5', color: '#7B1FA2' },
+ { bg: '#FCE4EC', color: '#C2185B' }
+];
+
+const getChipColor = (index) => chipColors[index % chipColors.length];
+
+function RecipeCard({ recipe }) {
+ const [expanded, setExpanded] = useState(false);
+
+ return (
+
+ {/* Fixed 10rem image */}
+
+
+
+
+
+
+
+
+
+ {/* Title */}
+
+ {recipe.recipe.label}
+
+
+ {/* Ingredient description */}
+
+ Made with {recipe.recipe.ingredientLines.join(', ')}.
+
+
+ {/* Health benefits toggle */}
+
+ }
+ size="small"
+ sx={{
+ minWidth: 0,
+ p: 0,
+ textTransform: 'none',
+
+ fontSize: '0.78rem',
+ fontWeight: 650,
+ color: '#388E3C',
+
+ '&:hover': {
+ backgroundColor: 'transparent'
+ }
+ }}
+ onClick={() => setExpanded((prev) => !prev)}
+ >
+ {expanded ? 'Hide benefits' : 'Health benefits'}
+
+
+ {/* Expandable section */}
+
+
+ {recipe.recipe.healthLabels.map((label, index) => {
+ const color = getChipColor(index);
+
+ return (
+
+ );
+ })}
+
+
+
+ {/* Read more */}
+ }
+ href={recipe.recipe.url}
+ sx={{
+ mt: 1.25,
+ height: 34,
+
+ borderRadius: '9px',
+
+ textTransform: 'none',
+ fontSize: '0.78rem',
+ fontWeight: 700,
+
+ backgroundColor: '#2E7D32',
+ boxShadow: 'none',
+
+ '&:hover': {
+ backgroundColor: '#1B5E20',
+ boxShadow: 'none'
+ }
+ }}
+ variant="contained"
+ >
+ Read more
+
+
+
+ );
+}
+
+export default function RecipeSlider({ recipes = [] }) {
+ return (
+
+ *': {
+ scrollSnapAlign: 'start'
+ },
+
+ scrollbarWidth: 'none',
+
+ '&::-webkit-scrollbar': {
+ display: 'none'
+ }
+ }}
+ >
+ {recipes.map((recipe) => (
+
+ ))}
+
+
+ );
+}
diff --git a/src/plays/pantry-alchemy/styles.css b/src/plays/pantry-alchemy/styles.css
new file mode 100644
index 000000000..5fd508fa9
--- /dev/null
+++ b/src/plays/pantry-alchemy/styles.css
@@ -0,0 +1 @@
+/* enter stlyes here */