I developed this API as part of my Software Engineering capstone project in April 2025. The goal was to build a backend that manages recipes, tracks ingredients across multiple recipes, and handles inventory changes when recipes are made.
The API was built to work with an Android application and uses PostgreSQL to store recipes, ingredients, users, and their relationships.
- TypeScript - Programming language
- Fastify - Backend API framework
- PostgreSQL - Relational database
- TypeORM - Database management and entity relationships
- JWT - User authentication
- Docker - Containerization
- Vitest - Unit testing
- User Authentication: Register, log in, log out, and manage user sessions using JWT.
- Recipe Management: Create, view, update, delete, and search recipes.
- Ingredient Management: Create, view, update, and delete ingredients.
- Recipe Ingredients: Associate multiple ingredients with recipes and manage the quantity needed for each recipe.
- Inventory Tracking: Keep track of available ingredients when recipes are made.
- Grocery List: Generate a grocery list based on ingredient inventory.
- Activity Logs: View ingredient activity and inventory changes.
All API endpoints use the /v1 prefix.
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/auth/register |
Register a user |
| POST | /v1/auth/login |
Log in |
| POST | /v1/auth/logout |
Log out |
| POST | /v1/auth/refresh-token |
Refresh authentication token |
| GET | /v1/auth/whoami |
Get authenticated user |
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/recipes |
Get all recipes |
| GET | /v1/recipes/:id |
Get a recipe |
| POST | /v1/recipes |
Create a recipe |
| PUT | /v1/recipes/:id |
Update a recipe |
| DELETE | /v1/recipes/:id |
Delete a recipe |
| GET | /v1/recipes/search |
Search recipes |
| POST | /v1/recipes/:recipeId/make |
Make a recipe |
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/recipes/:recipeId/ingredients |
Get ingredients associated with a recipe |
| GET | /v1/recipes/:recipeId/ingredients/:ingredientId |
Get a specific recipe ingredient |
| POST | /v1/recipes/:recipeId/ingredients/:ingredientId |
Associate an ingredient with a recipe |
| PUT | /v1/recipes/:recipeId/ingredients/:ingredientId |
Update a recipe ingredient |
| DELETE | /v1/recipes/:recipeId/ingredients/:ingredientId |
Remove an ingredient from a recipe |
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/ingredients |
Get all ingredients |
| GET | /v1/ingredients/:id |
Get an ingredient |
| POST | /v1/ingredients |
Create an ingredient |
| PUT | /v1/ingredients/:id |
Update an ingredient |
| DELETE | /v1/ingredients/:id |
Delete an ingredient |
| GET | /v1/ingredients/:recipeId/available |
Get ingredients not associated with a recipe |
| GET | /v1/ingredients/logs |
Get ingredient activity logs |
| GET | /v1/ingredients/grocery |
Generate a grocery list |
All recipe and ingredient endpoints require authentication.
- Node.js
- PostgreSQL
- npm
- Docker (optional)
Clone the repository and navigate to the API directory.
cd apiInstall the dependencies.
npm installCreate a .env file using .env.example and configure your database and authentication settings.
PORT=8081
INTERFACE=localhost
JWT_SECRET=your_jwt_secret
COOKIE_SECRET=your_cookie_secret
SESSION_SECRET=your_session_secret
DB_NAME=recipe_app
DB_USER=postgres
DB_PASS=your_database_password
DB_HOST=localhost
DB_PORT=5432Make sure PostgreSQL is running and the database credentials are configured correctly.
Start the development server.
npm run dev| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Compile TypeScript |
npm start |
Start compiled application |
npm test |
Run unit tests |
npm run lint |
Run linting and formatting |
The following diagram shows the structure and relationships between users, recipes, ingredients, and other related entities.
api/
├── src/
│ ├── controllers/
│ ├── models/
│ ├── repositories/
│ ├── routes/
│ │ └── v1/
│ ├── services/
│ ├── utils/
│ ├── __test__/
│ └── index.ts
├── scripts/
├── .env.example
├── docker-compose.yml
├── Dockerfile
└── package.json
The API is organized into controllers, services, and repositories to separate request handling, business logic, and database operations.
