{"id":31158079,"url":"https://github.com/arnobt78/food-recipe-spoonacular--react-fullstack","last_synced_at":"2025-09-18T23:30:45.359Z","repository":{"id":312324057,"uuid":"1046562701","full_name":"arnobt78/Food-Recipe-Spoonacular--React-FullStack","owner":"arnobt78","description":"A modern, full-stack recipe management application. Search for recipes, view details, and manage favourites with a beautiful React frontend and a robust Node.js/Express backend powered by PostgreSQL and the Spoonacular API.","archived":false,"fork":false,"pushed_at":"2025-08-29T19:37:47.000Z","size":3405,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-29T21:48:15.699Z","etag":null,"topics":["api-integration","expressjs","food-recipe-app","food-recipe-web-app","food-recipe-website","food-recipes","manage-favourites","modular-components","nodejs","postgresql","prisma","raw-css","react-vite-typescript","recipe-details","recipe-management","recipe-search","restful-api","search-recipes","spoonacular","spoonacular-api"],"latest_commit_sha":null,"homepage":"https://food-recipe-spoonacular.netlify.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arnobt78.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-28T21:50:04.000Z","updated_at":"2025-08-29T19:45:56.000Z","dependencies_parsed_at":"2025-08-29T21:48:17.539Z","dependency_job_id":"bf937799-ec4f-42e9-b758-6349c4d2894a","html_url":"https://github.com/arnobt78/Food-Recipe-Spoonacular--React-FullStack","commit_stats":null,"previous_names":["arnobt78/recipe-web-app--react-fullstack"],"tags_count":null,"template":true,"template_full_name":null,"purl":"pkg:github/arnobt78/Food-Recipe-Spoonacular--React-FullStack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FFood-Recipe-Spoonacular--React-FullStack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FFood-Recipe-Spoonacular--React-FullStack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FFood-Recipe-Spoonacular--React-FullStack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FFood-Recipe-Spoonacular--React-FullStack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arnobt78","download_url":"https://codeload.github.com/arnobt78/Food-Recipe-Spoonacular--React-FullStack/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FFood-Recipe-Spoonacular--React-FullStack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275852055,"owners_count":25540136,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-18T02:00:09.552Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-integration","expressjs","food-recipe-app","food-recipe-web-app","food-recipe-website","food-recipes","manage-favourites","modular-components","nodejs","postgresql","prisma","raw-css","react-vite-typescript","recipe-details","recipe-management","recipe-search","restful-api","search-recipes","spoonacular","spoonacular-api"],"created_at":"2025-09-18T23:30:40.832Z","updated_at":"2025-09-18T23:30:45.312Z","avatar_url":"https://github.com/arnobt78.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Food Recipe Spoonacular Website - React, Node.js, PostgreSQL FullStack Project\n\n![Screenshot 2025-08-29 at 21 29 48](https://github.com/user-attachments/assets/07100269-526c-49d7-9045-36dd3008a1ce)\n![Screenshot 2025-08-29 at 21 30 18](https://github.com/user-attachments/assets/4eeeaa08-13cb-4d5a-9759-1097d80bf290)\n![Screenshot 2025-08-29 at 21 30 35](https://github.com/user-attachments/assets/958fe32b-4201-4bbf-957d-f577b8ae10f1)\n\n---\n\nA modern, full-stack recipe management application. Search for recipes, view details, and manage favourites with a beautiful React frontend and a robust Node.js/Express backend powered by PostgreSQL and the Spoonacular API.\n\n- **Frontend-Live-Demo:** [https://food-recipe-spoonacular.netlify.app/](https://food-recipe-spoonacular.netlify.app/)\n- **Backend-Live-Demo:** [https://recipe-app-glt5.onrender.com](https://recipe-app-glt5.onrender.com)\n\n---\n\n## Table of Contents\n\n- [Project Overview](#project-overview)\n- [Project Structure](#project-structure)\n- [Features \u0026 Functionality](#features--functionality)\n- [Environment Variables (.env)](#environment-variables-env)\n- [Setup \u0026 Usage](#setup--usage)\n- [API Endpoints](#api-endpoints-backend)\n- [Frontend Walkthrough](#frontend-walkthrough)\n- [Backend Walkthrough](#backend-walkthrough)\n- [Reusing \u0026 Extending](#reusing--extending)\n- [Tech Stack \u0026 Keywords](#tech-stack--keywords)\n- [Conclusion](#conclusion)\n- [Happy Coding! 🎉](#happy-coding-)\n\n---\n\n## Project Overview\n\nThis project is a full-stack web app for discovering and saving recipes. It consists of:\n\n- **Frontend**: React + TypeScript (Vite), modern UI, responsive, easy to extend.\n- **Backend**: Node.js + Express + TypeScript, REST API, PostgreSQL (via Prisma), integrates with Spoonacular API.\n\nUsers can search for recipes, view summaries, and manage their favourites. The app is modular, well-documented, and ready for learning or extension.\n\n---\n\n## Project Structure\n\n```bash\nrecipe-app/\n├── recipe-app-backend/    # Backend (Node.js, Express, Prisma, PostgreSQL)\n│   ├── .env\n│   ├── package.json\n│   ├── prisma/\n│   │   └── schema.prisma\n│   └── src/\n│       ├── index.ts\n│       └── recipe-api.ts\n├── recipe-app-frontend/   # Frontend (React, Vite, TypeScript)\n│   ├── .env\n│   ├── package.json\n│   ├── public/\n│   │   ├── hero-image.webp\n│   │   └── vite.svg\n│   └── src/\n│       ├── App.tsx\n│       ├── App.css\n│       ├── api.ts\n│       ├── main.tsx\n│       ├── types.ts\n│       └── components/\n│           ├── RecipeCard.tsx\n│           └── RecipeModal.tsx\n└── README.md              # (You are here)\n```\n\n---\n\n## Features \u0026 Functionality\n\n- **Recipe Search**: Search recipes by keyword (Spoonacular API)\n- **Recipe Details**: View recipe summary in a modal\n- **Favourites**: Add/remove recipes to your favourites, view in a separate tab\n- **Responsive UI**: Works on desktop and mobile\n- **TypeScript**: Type safety throughout\n- **API Integration**: Connects frontend and backend seamlessly\n- **Modular Code**: Easy to extend and reuse\n\n---\n\n## Environment Variables (.env)\n\n### Backend (`recipe-app-backend/.env`)\n\n```env\nAPI_KEY=your_spoonacular_api_key\nDATABASE_URL=your_postgresql_connection_string\n```\n\n- **API_KEY**: Get from [Spoonacular](https://spoonacular.com/food-api)\n- **DATABASE_URL**: Get from your PostgreSQL provider (Render, Supabase, Neon, Railway, etc.)\n\n### Frontend (`recipe-app-frontend/.env`)\n\n```env\nVITE_API_URL=http://localhost:5005\n```\n\n- **VITE_API_URL**: The base URL for your backend API. Use your deployed backend URL in production.\n\n---\n\n## Setup \u0026 Usage\n\n### 1. Backend\n\n```bash\ncd recipe-app-backend\nnpm install\n# Configure .env as above\nnpx prisma migrate dev --name init\nnpm start\n```\n\nAPI will be available at: `http://localhost:5005/api/recipes/...`\n\n### 2. Frontend\n\n```bash\ncd recipe-app-frontend\nnpm install\n# Configure .env as above\nnpm run dev\n```\n\nOpen [http://localhost:5173](http://localhost:5173) in your browser.\n\n---\n\n## API Endpoints (Backend)\n\n- `GET /api/recipes/search?searchTerm=\u003cterm\u003e\u0026page=\u003cpage\u003e` — Search recipes\n- `GET /api/recipes/:recipeId/summary` — Get recipe summary\n- `POST /api/recipes/favourite` — Add favourite `{ \"recipeId\": 12345 }`\n- `GET /api/recipes/favourite` — List favourites\n- `DELETE /api/recipes/favourite` — Remove favourite `{ \"recipeId\": 12345 }`\n\n---\n\n## Frontend Walkthrough\n\n### Main App (`App.tsx`)\n\n- Manages state, tabs, search, favourites, and modal.\n- Handles API calls via `api.ts`.\n\n#### Example: Search Recipes\n\n```tsx\nconst handleSearchSubmit = async (event: FormEvent) =\u003e {\n  event.preventDefault();\n  setApiError(\"\");\n  try {\n    const response = await api.searchRecipes(searchTerm, 1);\n    if (response.status === \"failure\" || response.code === 402) {\n      setApiError(response.message || \"API quota reached.\");\n      setRecipes([]);\n    } else {\n      setRecipes(Array.isArray(response.results) ? response.results : []);\n      pageNumber.current = 1;\n    }\n  } catch (e) {\n    setRecipes([]);\n  }\n};\n```\n\n### API Integration (`api.ts`)\n\n- Handles all API requests to the backend.\n\n#### Example: Add Favourite Recipe\n\n```typescript\nexport const addFavouriteRecipe = async (recipe: Recipe) =\u003e {\n  const url = new URL(\"/api/recipes/favourite\", API_URL);\n  const body = { recipeId: recipe.id };\n  const response = await fetch(url, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify(body),\n  });\n  if (!response.ok) {\n    throw new Error(`HTTP error! Status: ${response.status}`);\n  }\n};\n```\n\n### Components\n\n- **RecipeCard**: Displays a recipe card with image, title, and favourite button.\n- **RecipeModal**: Shows a modal with the recipe summary and title.\n\n#### Example: Using RecipeCard\n\n```tsx\n\u003cRecipeCard\n  key={recipe.id}\n  recipe={recipe}\n  onClick={() =\u003e setSelectedRecipe(recipe)}\n  onFavouriteButtonClick={\n    isFavourite ? removeFavouriteRecipe : addFavouriteRecipe\n  }\n  isFavourite={isFavourite}\n/\u003e\n```\n\n---\n\n## Backend Walkthrough\n\n### Main Server (`src/index.ts`)\n\n- Sets up Express, CORS, and JSON parsing.\n- Defines all API routes for search, summary, and favourites.\n\n### Spoonacular Integration (`src/recipe-api.ts`)\n\n- Handles all external API requests.\n- Functions: `searchRecipes`, `getRecipeSummary`, `getFavouriteRecipesByIDs`.\n\n### Prisma Schema (`prisma/schema.prisma`)\n\n```prisma\nmodel FavouriteRecipes {\n  id       Int @id @default(autoincrement())\n  recipeId Int @unique\n}\n```\n\n---\n\n## Reusing \u0026 Extending\n\n- **Frontend**: Components and API functions are modular and reusable. Add new features by following the existing structure.\n- **Backend**: Add new endpoints or models in a RESTful, modular way. Use Prisma for DB migrations.\n\n### Example: Add a New API Call (Frontend)\n\n```typescript\nexport const getRecipeInstructions = async (recipeId: string) =\u003e {\n  const url = new URL(`/api/recipes/${recipeId}/instructions`, API_URL);\n  const response = await fetch(url);\n  if (!response.ok) throw new Error(\"Failed to fetch instructions\");\n  return response.json();\n};\n```\n\n### Example: Add a New Endpoint (Backend)\n\n```ts\napp.get(\"/api/recipes/:id/instructions\", async (req, res) =\u003e {\n  // Call Spoonacular for instructions\n});\n```\n\n---\n\n## Tech Stack \u0026 Keywords\n\n- **React**\n- **TypeScript**\n- **Vite**\n- **Node.js**\n- **Express**\n- **Prisma**\n- **PostgreSQL**\n- **Spoonacular API**\n- **REST API**\n- **Modular Components**\n- **Hooks**\n- **Responsive Design**\n- **API Integration**\n- **Reusable UI**\n\n---\n\n## Conclusion\n\nThis project is a modern, extensible, and user-friendly full-stack recipe app. It demonstrates best practices in React, TypeScript, API integration, backend design, and UI/UX. Use it as a learning resource, a starter for your own projects, or as a foundation for your next app.\n\n---\n\n## Happy Coding! 🎉\n\nFeel free to use this project repository and extend this project further!\n\nIf you have any questions or want to share your work, reach out via GitHub or my portfolio at [https://arnob-mahmud.vercel.app/](https://arnob-mahmud.vercel.app/).\n\n**Enjoy building and learning!** 🚀\n\nThank you! 😊\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farnobt78%2Ffood-recipe-spoonacular--react-fullstack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farnobt78%2Ffood-recipe-spoonacular--react-fullstack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farnobt78%2Ffood-recipe-spoonacular--react-fullstack/lists"}