Firebase Genkit is a powerful framework for building AI-powered applications with TypeScript. This codelab will guide you through three essential patterns for working with Genkit: basic AI generation, prompt management with .prompt files, and building reusable flows.

📚 Additional Resources:

What you'll learn

What you'll need

📚 Additional Resources:

What you'll build

By the end of this codelab, you'll have built three practical business examples:

  1. A professional communication generator (emails, bug reports) using ai.generate
  2. A project planning assistant using .prompt files
  3. A complete content analysis flow for team communications and documentation

Before we start building, let's set up a new Genkit project.

Initialize your project

First, create a new directory and initialize a Node.js project:

mkdir genkit-workshop
cd genkit-workshop
npm init -y

Install Genkit packages

First, install the Genkit CLI globally:

npm install -g genkit-cli

Then, add the following packages to your project:

npm install genkit @genkit-ai/google-genai
npm install -D typescript tsx @types/node

Configure TypeScript

Create a tsconfig.json file:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Set up environment variables

Create a .env file in your project root:

# Get your API key from https://aistudio.google.com/apikey
GEMINI_API_KEY=your_google_ai_api_key_here

Important: Never commit your API keys to version control. Create a .gitignore file:

node_modules/
.env
dist/
*.log

Install dotenv for environment variables

npm install dotenv

Verify your setup

Let's make sure everything is working correctly:

# Check Node.js version (should be 18+)
node --version

# Check npm version
npm --version

# Verify TypeScript compilation works
npx tsc --version

If any command fails, please install the missing dependencies using the links provided above.

📚 Additional Resources:

Let's start with the simplest way to use Genkit: direct AI generation using the ai.generate API.

Create the basic generator

Create src/example1-basic.ts:

import { googleAI } from '@genkit-ai/google-genai';
import { genkit } from 'genkit';
import 'dotenv/config';

// Initialize Genkit with Google AI
const ai = genkit({
  plugins: [googleAI()],
  model: 'gemini-2.5-flash',
});

async function basicGeneration() {
  try {
    // Simple text generation
    const response = await ai.generate({
      prompt: 'Write a short welcome message for a new team member joining our development team.',
    });

    console.log('Generated message:');
    console.log(response.text());
  } catch (error) {
    console.error('Error generating content:', error);
  }
}

// Run the example
basicGeneration();

Run your first example

Execute the basic generation example:

npx tsx src/example1-basic.ts

You should see a generated welcome message!

Try different prompts

Let's try a few more simple examples. Update src/example1-basic.ts:

import { googleAI } from '@genkit-ai/google-genai';
import { genkit } from 'genkit';
import 'dotenv/config';

// Initialize Genkit with Google AI
const ai = genkit({
  plugins: [googleAI()],
  model: 'gemini-2.5-flash',
});

async function basicGeneration() {
  try {
    // Example 1: Generate a welcome message
    console.log('=== Welcome Message ===');
    const welcomeResponse = await ai.generate({
      prompt: 'Write a short welcome message for a new team member joining our development team.',
    });
    console.log(welcomeResponse.text());

    // Example 2: Create a simple task list
    console.log('\n=== Task List ===');
    const taskResponse = await ai.generate({
      prompt: 'Create a simple 3-item todo list for setting up a new development environment.',
    });
    console.log(taskResponse.text());

    // Example 3: Write a brief explanation
    console.log('\n=== Explanation ===');
    const explanationResponse = await ai.generate({
      prompt: 'Explain what TypeScript is in 2-3 simple sentences.',
    });
    console.log(explanationResponse.text());
  } catch (error) {
    console.error('Error generating content:', error);
  }
}

// Run the example
basicGeneration();

Test with Firebase Studio

Start Firebase Studio to test your generation interactively:

genkit start -- tsx --watch src/index.ts

This will open the Genkit Developer UI in your browser where you can test your AI generation with different prompts and see the results in real-time.

📚 Additional Resources:

Managing prompts in separate files makes them more maintainable and allows for better collaboration. Let's create a simple story generator using .prompt files.

Create your first prompt file

Create a directory for prompts at your project root and add your first prompt file:

mkdir prompts

Create prompts/story-generator.prompt:

---
model: googleai/gemini-2.5-flash
input:
  schema:
    character: string
    setting: string
---

Write a short, fun story (2-3 paragraphs) about {{character}} in {{setting}}.
Keep it light-hearted and suitable for all ages.

Create the prompt-based generator

Create src/example2-prompts.ts:

import { googleAI } from '@genkit-ai/google-genai';
import { genkit } from 'genkit';
import 'dotenv/config';

// Initialize Genkit with Google AI
const ai = genkit({
  plugins: [googleAI()],
});

// Load the prompt from the file
const storyGeneratorPrompt = ai.prompt('story-generator');

async function generateStory() {
  try {
    console.log('=== Generating Story with Prompt File ===');

    const storyInput = {
      character: 'a friendly robot',
      setting: 'a magical library',
    };

    console.log('Story parameters:');
    console.log(`Character: ${storyInput.character}`);
    console.log(`Setting: ${storyInput.setting}`);

    const response = await storyGeneratorPrompt(storyInput);

    console.log('\n=== Generated Story ===');
    console.log(response.text());
  } catch (error) {
    console.error('Error generating story:', error);
  }
}

// Generate different stories
async function generateDifferentStories() {
  const stories = [
    { character: 'a curious cat', setting: 'a space station' },
    { character: 'a young wizard', setting: 'a bustling marketplace' },
    { character: 'a brave explorer', setting: 'an underwater city' },
  ];

  for (const story of stories) {
    console.log(`\n=== Story: ${story.character} in ${story.setting} ===`);
    const response = await storyGeneratorPrompt(story);
    console.log(response.text());
    console.log('\n' + '='.repeat(50));
  }
}

// Run examples
async function main() {
  await generateStory();
  await generateDifferentStories();
}

main();

Create another simple prompt

Let's create another prompt for generating simple recipes. Create prompts/recipe-generator.prompt:

---
model: googleai/gemini-2.5-flash
input:
  schema:
    ingredient: string
    mealType: string
---

Create a simple recipe for {{mealType}} using {{ingredient}} as the main ingredient.
Keep it easy to follow with basic ingredients and simple steps.

Test your prompts

Run the prompt-based example:

npx tsx src/example2-prompts.ts

You should see several different stories generated using your prompt file!

View prompts in the Developer UI

With the Developer UI running (genkit start -- tsx --watch src/index.ts), you can see your prompts listed in the interface and test them with different inputs interactively.

📚 Additional Resources:

Flows are reusable functions that can be called, tested, and monitored. They're perfect for building simple AI workflows.

Create a basic greeting flow

Create src/example3-flows.ts:

import { googleAI } from '@genkit-ai/google-genai';
import { genkit, z } from 'genkit';
import 'dotenv/config';

// Initialize Genkit with Google AI
const ai = genkit({
  plugins: [googleAI()],
  model: 'gemini-2.5-flash',
});

// Define a simple greeting flow
export const greetingFlow = ai.defineFlow(
  {
    name: 'greeting',
    inputSchema: z.object({
      name: z.string().describe("The person's name"),
      language: z.enum(['english', 'spanish', 'french']).describe('Language for greeting'),
    }),
    outputSchema: z.object({
      greeting: z.string().describe('The generated greeting'),
    }),
  },
  async ({ name, language }) => {
    // Generate the greeting
    const response = await ai.generate({
      prompt: `Create a friendly greeting for ${name} in ${language}. Keep it warm and welcoming.`,
    });

    return {
      greeting: response.text().trim(),
    };
  },
);

// Define a joke generator flow
export const jokeFlow = ai.defineFlow(
  {
    name: 'jokeGenerator',
    inputSchema: z.object({
      topic: z.string().describe('The topic for the joke'),
    }),
    outputSchema: z.object({
      joke: z.string().describe('The generated joke'),
    }),
  },
  async ({ topic }) => {
    // Generate a clean, family-friendly joke
    const response = await ai.generate({
      prompt: `Create a clean, family-friendly joke about ${topic}. Keep it short and funny.`,
    });

    return {
      joke: response.text().trim(),
    };
  },
);

// Example usage function
async function demonstrateFlows() {
  try {
    console.log('=== Testing Greeting Flow ===');

    const greetingResult = await greetingFlow({
      name: 'Alice',
      language: 'english',
    });

    console.log('Greeting Result:');
    console.log(greetingResult.greeting);

    console.log('\n=== Testing Joke Flow ===');

    const jokeResult = await jokeFlow({
      topic: 'programming',
    });

    console.log('Joke Result:');
    console.log(jokeResult.joke);

    console.log('\n=== Testing Multiple Greetings ===');
    const people = [
      { name: 'Bob', language: 'spanish' as const },
      { name: 'Claire', language: 'french' as const },
    ];

    for (const person of people) {
      const result = await greetingFlow(person);
      console.log(`${person.name} (${person.language}): ${result.greeting}`);
    }
  } catch (error) {
    console.error('Error running flows:', error);
  }
}

// Run the demonstration
demonstrateFlows();
### Create a package.json script

Add a script to your `package.json` to easily run the flows:

```json
{
  "scripts": {
    "example1": "tsx src/example1-basic.ts",
    "example2": "tsx src/example2-prompts.ts",
    "example3": "tsx src/example3-flows.ts",
    "studio": "genkit start"
  }
}

Test your flows

Run the flows example:

npm run example3

Test flows in the Developer UI

Start the Developer UI and navigate to the Flows section:

genkit start -- tsx --watch src/index.ts

In the Developer UI, you'll be able to:

📚 Additional Resources:

Firebase Studio provides a powerful interface for testing and debugging your Genkit applications.

Key Features of Firebase Studio

  1. Flow Testing: Interactive testing of your flows with custom inputs
  2. Prompt Management: Visual editor for your prompts with real-time testing
  3. Model Comparison: Test the same prompt with different models side by side
  4. Execution Traces: Detailed view of each step in your flows
  5. Performance Monitoring: Track response times and token usage

Best Practices for Testing

  1. Start Simple: Test basic functionality before adding complexity
  2. Use Diverse Inputs: Test with various input types and edge cases
  3. Monitor Performance: Watch token usage and response times
  4. Iterate on Prompts: Use Studio to refine your prompts for better results
  5. Version Control: Keep track of prompt changes and their performance

📚 Additional Resources:

Debugging Common Issues

API Key Problems

Error: Failed to authenticate with Google AI

Schema Validation Errors

Error: Output doesn't match expected schema

Rate Limiting

Error: Rate limit exceeded

📚 Additional Resources:

Congratulations! You've learned the fundamentals of Firebase Genkit with TypeScript. Here's what you can explore next:

Intermediate Topics

Advanced Topics

Useful Resources

  1. Official Documentation: Firebase Genkit Docs
  2. GitHub Repository: Genkit GitHub
  3. Community: Firebase Discord
  4. Examples: Genkit Samples

Sample Projects to Build

  1. AI Content Assistant: Blog post generator with SEO optimization
  2. Code Review Bot: Automated code analysis and suggestions
  3. Customer Service Chatbot: Multi-turn conversations with context
  4. Document Processor: Extract and analyze information from PDFs
  5. Language Learning App: Personalized lessons and practice exercises

📚 Additional Resources:

Common Issues and Solutions

Issue: "Module not found" errors

npm install --save-dev @types/node
npm install dotenv

Issue: TypeScript compilation errors

npx tsc --noEmit  # Check for type errors

Issue: "tsx command not found"

npm install -g tsx  # Install tsx globally, or use npx tsx

Issue: Firebase Studio not starting

npx genkit start --port 4000  # Try different port

Issue: API rate limits

Getting Help

📚 Additional Resources:

You've successfully built three different patterns for working with Firebase Genkit:

  1. Direct AI Generation: Quick and simple for basic use cases
  2. Prompt Management: Organized and maintainable for complex prompts
  3. Flows: Powerful and reusable for complex AI workflows

These patterns form the foundation for building sophisticated AI-powered applications. Start with simple use cases and gradually build more complex workflows as you become comfortable with the framework.

📚 Continue Your Journey:

Happy building with Firebase Genkit! 🚀