
Food Fit: Your Partner for Healthy Eating with Genkit 🍎
In this guide, you will learn how to build a web application with Genkit, Gemini 2.0 Flash, and Imagen 3 to generate healthy recipes and deploy it on Firebase.
What is Genkit?
Genkit is the framework developed by Google for building AI-powered applications. It is designed to work with many AI model providers and vector databases.
What is Gemini 2.0 Flash?
Gemini 2.0 Flash is a mid-size multimodal model that is optimized for a wide variety of reasoning tasks.
What is Imagen 3?
It is Google’s image generation model, which can be used for creating images from text.
Now that we know what tools we will use, let’s see how they integrate into our application’s architecture.

The application we create will be deployed on Firebase Hosting, taking advantage of the different services Firebase offers. For the backend, we will use Cloud Functions, which allows us to quickly create a function and implement it with Genkit flows. Finally, we will implement Imagen 3 and Gemini 2.0 Flash to generate the content.
In Genkit, a ‘flow’ is an AI-based content generation workflow. We will define three: one to suggest recipes, another to list options, and another to generate images of the dishes.
Steps to Build the Application
Create the project in the Firebase console.
As I mentioned above, we will use Cloud Functions, and it is a service that requires upgrading to the paid plan (Blaze). However, if we do not exceed the quota, we will not incur any costs.
Remember to always add billing alerts to control cloud usage. I have an article where I explain Google Cloud Platform billing.

After that, create the project and install the Genkit dependencies. To avoid repeating this step in every project with Genkit, I have created a boilerplate that already has the necessary dependencies to start the project.
If you have any questions about the boilerplate, you can leave me a comment or write to me on X.
To use the Gemini API, you will need an API key. If you don’t have one yet, create a key in Google AI Studio.
Also, remember to enable the Vertex AI API to be able to use it in our project.

After configuring the API in the project, when running the project locally, the following will be displayed:

We will go to the index.ts file and paste the following code:
require('dotenv').config();
import { z, genkit } from 'genkit';
import { gemini20Flash001, imagen3, vertexAI } from '@genkit-ai/vertexai';
// Construimos los esquemas que nos ayudarán para tener una estructura de salida en cada flujo.
const outputFoodItemSchema = z.object({
name: z.string(),
description: z.string(),
ingredients: z.array(z.string()),
nutritional_information: z.object({
cal: z.number(),
carbohydrates: z.number(),
fats: z.number(),
sodium: z.number(),
cholesterol: z.number(),
proteins: z.number(),
}),
preparation_time: z.string(),
level: z.string(),
preparation: z.array(z.string()),
});
const inputSchema = z.object({
ingredient: z.string(),
quantity_people: z.number()
});
// Configuramos Genkit
const ai = genkit({
plugins: [
vertexAI({ location: 'us-central1' }),
],
});
// Creamos los flujos
export const foodSuggestionFlow = ai.defineFlow(
{
name: 'foodSuggestionFlow',
inputSchema: inputSchema,
outputSchema: z.array(outputFoodItemSchema),
},
async (payload) => {
const { output } = await ai.generate({
model: gemini20Flash001,
prompt: `
Eres el asistente de inteligencia artificial más experto en gastronomía.
Genera un lista de 4 recetas para una persona que quiere alimentarse de forma saludable.
En la matriz de las recetas, coloque las recetas como lo haría un recetario de comida.
Las recetas deben contener ${payload.ingredient} como ingrediente principal.
Dale a cada receta una descripción única.
Las recetas deben ser saludables y equilibradas. Además que sean para ${payload.quantity_people} personas.
Las recetas tienen que estar en español.
Limite las descripciones de las recetas a 7 palabras.
`,
output: { schema: z.array(outputFoodItemSchema) }
});
if (output == null) {
throw new Error("Response doesn't satisfy schema.");
}
return output;
}
);
export const listFoodsSuggestionFlow = ai.defineFlow(
{
name: 'listFoodsSuggestionFlow',
outputSchema: z.array(outputFoodItemSchema),
},
async () => {
const { output } = await ai.generate({
model: gemini20Flash001,
prompt: `Eres el asistente de inteligencia artificial más experto en gastronomía.
Genera un lista de 4 recetas para una persona que quiere alimentarse de forma saludable.
En la matriz de las recetas, coloque las recetas como lo haría un recetario de comida.
Dale a cada receta una descripción única.
Las recetas deben ser saludables y equilibradas. Además que sean para 4 personas.
Las recetas tienen que estar en español.
Limite las descripciones de las recetas a 7 palabras.`,
output: { schema: z.array(outputFoodItemSchema) }
});
if (output == null) {
throw new Error("Response doesn't satisfy schema.");
}
return output;
}
);
export const generateImageFoodFlow = ai.defineFlow(
{
name: 'generateImageFoodFlow',
inputSchema: z.object({
food: z.string(),
})
},
async (payload) => {
const response = await ai.generate({
model: imagen3,
prompt: `Photo of the Peruvian dish ${payload.food}`,
output: { format: 'media' },
});
if (response == null) {
throw new Error("Response doesn't satisfy schema.");
}
return response.message.content[0].media;
}
);
And we will see that in the Genkit UI, the created flows will appear: foodSuggestionFlow, listFoodsSuggestionFlow, and generateImageFoodFlow.

foodSuggestionFlow: This is the flow created to suggest healthy dishes by passing a food item and the number of people as parameters.
listFoodsSuggestionFlow: This is the flow created to suggest healthy dishes.
generateImageFoodFlow: This is the flow created to generate the image of the dish from its name.
We can use the dashboard to test the flow and its response. Additionally, we can track the flow and see if anything went wrong.

I am attaching the project where you can find a file named index.local.ts with the complete configuration. Remember to update your API KEY.
Now that we have our flows created, we proceed to create the Cloud Functions, where we will add the firebase-functions dependency and add a small piece of code to our flows.
We have already defined the foodSuggestionFlow to generate healthy recipes. Now we will integrate it with Firebase Functions to be able to consume it from our application.
export const foodSuggestionFlowFunction = onCallGenkit({
authPolicy: () => true,
secrets: [googleAIapiKey],
cors: '*'
}, foodSuggestionFlow);
We create a function called foodSuggestionFlowFunction where I use the onCallGenkit method to configure the function in the cloud and pass our foodSuggestionFlow.
When deploying the Cloud Functions in Firebase, we will be able to see it from the Firebase dashboard.

Then, all that remains is to obtain the data by making the request from the Angular application.

I am leaving the complete repository with the full flows, the cloud functions, and the project configuration.
Additionally, I am leaving the final result of the project.
I will take advantage of the application and look for a recipe for dinner. 🥗 If you are interested in learning more about Genkit and Vertex AI, you can leave me a comment with your questions.
This article was translated into English by Gemini. The actual article is available in Spanish at the following link.