You can visit the deployed demo at https://recipeamigo.eetumaenpaa.fi.
Recipeamigo is a platform where you can create and share recipes with other people. You can group recipes into collections, such as "Easy to prepare" or "My in-laws' favorites". You can like recipes to save them for later. Each recipe and recipe collection has a visibility that can be set to either public, unlisted or private. Recipes can be tagged with tags, such as "Lactose-free" or "Vegetarian".
The application features localization for English and Finnish, and there are a light and dark theme available. It is also fully responsive on mobile screen sizes.
The recipe editor has an exhaustive list of existing, localized ingredients. It combines the ingredient name, amount and unit into a natural sounding result, such as "2 kilograms of tomatoes" or "1 liter of milk". This works for both languages. The instruction editor allows you to embed timers into the instructions, making the cooking process easier.
The browse page allows you to search all the public recipes that exist. You can filter by many properties, such as title, tags, preparation time or by excluding specific ingredients. The results can be sorted and they are paginated.
There are a total of 200+ integration and unit tests to make sure the API works and is secure. The project has a CI/CD pipeline that checks linting, formatting and tests on each commit, as well as deploys the project to Vercel.
This is my submission for the Full Stack Open project. The time logging is at docs/timelog.md.
- React
- Next.js
- TypeScript
- ESLint + Prettier
- PostgreSQL (database)
- Minio (S3/object storage)
- Clerk (authentication)
- Vercel (deployment)
- Vitest (unit & integration testing)
- Prisma (ORM)
- i18next (localization)
- Zod (validation)
- Tiptap (rich text editor for instructions)
- PDFKit (PDF generation)
- react-hot-toast (toast notifications)
The app is hosted on Vercel, and uses Clerk for authentication. The database and S3/object storage are hosted on a Linux/Ubuntu server from OVH (1vCPU, 2GB RAM, 20GB SSD).
Things you need:
- S3 instance (tested with Minio, but should with with others as well)
- PostgreSQL instance
- Hosting the app itself (e.g. Vercel)
- Clerk.com account (auth provider)
Things you need:
- Node.js (tested with Node.js 18)
- Docker (or PostgreSQL and Minio hosted somehow)
- Clerk.com account
- Clone the repository with
git clone https://github.com/Eldemarkki/recipeamigo.git
- Run
npm install
- Create a
.env.local
file based on.env.local.example
, and fill in the missing fields for Clerk. - Run the PostgreSQL database and Minio with
docker compose -f compose-dev.yaml up
- Generate the Prisma schema:
prisma generate
- Apply migrations to the database:
npm run migrate:dev
- Run
npm run dev
- Go to http://localhost:3000
- Passwordless login
- Public recipes
- Edit recipe
- Recipe cover image upload
- Recipe image gallery
- Reference ingredient in instructions
- Themes (light/dark/others)
- Localization (English, Finnish)
- Metric/Imperial conversion
- Mobile friendly
- Print recipe
- Export recipe
- JSON
- Markdown
- Recipe time estimation (manual)
- Browse recipes
- Exclude recipes with certain ingredients
- Only vegetarian, gluten-free, etc.
- Less than X minutes
- Recipe tags/categories
- Likes
- Collection for showing liked recipes
- Save recipes to collections
- Private collections
- Public collections
- Unlisted collections
- Embedded timer ("cook for 5 minutes", click to start timer)
- Simple instructions-view (big font, no bloat)
- Notes/tips/warnings among instructions
- "I have these ingredients, what can I make?"
- How many times has a recipe been viewed
- Recipe importing (JSON)
- Required tools (e.g. oven, blender, etc.)
- Ingredient substitution (e.g. "use 1/2 cup of milk instead of 1/2 cup of cream")
- Share to social media
- Ingredient bank (standardized ingredient names so that they can be translated)
- "Forking" a recipe (copying it to your own account, with a link to the original)
- Text area for the "story" of the recipe that can be collapsed to hide it
- Optional ingredients
- Share links
- Private (only visible to author)
- Public (partially done, requires implementing the Browse view)
- Listed in Browse view
- Unlisted, only visible with direct link
- Password protected
- Share with selected registered users
- Draft status (only visible to author)