In my previous article, we looked at the Google AI Dart SDK and how we can use it in Flutter/Dart applications. I promised to provide a sample application in the upcoming article, so here I am today. We will develop a storytelling application in Flutter using the Google Generative AI package. So, without further ado, let's start.
An AI Storytelling App
Let's make a small storyteller app using Flutter and Gemini AI. In this app, we will provide the prompt and image to Gemini AI, which will respond with a story based on the image, as shown in the app flow diagram below.

Now, join me in completing these steps to build it.
Step 1. Installation
Follow the steps below to enable Google Gemini in your Flutter project.
Get an API key: You can head over to https://aistudio.google.com/app/apikey and create a Gemini API key.
Add the dependency: You need to add the google_generative_ai dependency to the pubspec.yaml file in your flutter project.
dependencies:
google_generative_ai: ^0.2.0
Add the assets: You must include the image assets folder in your pubspec.yaml file.
assets:
- images/
Run the Flutter pub and get after that.
Step 2. Folder Structure
Create a folder structure similar to the one shown below, and put all of your images in the image folder.

Step 3. Add Your API Key
Add the Gemini API key to the utils/constants.dart file.
const String apiKey = 'YOUR_API_KEY';
Replace the YOUR_API_KEY with your actual Gemini API key.
Step 4. Add Images Resources
In the utils/images.dart file, I've centralized all of the asset image paths.
class ImageResources {
static const String elephantAndTailor = 'images/elephant-and-the-tailor.jpg';
static const String freeBird = 'images/free_bird.jpeg';
static const String lionAndMouse = 'images/lion_and_mouse.jpeg';
static const String lionAndRabbit = 'images/lion_and_rabbit.jpeg';
static const String lostAndFound = 'images/lost_and_found.jpeg';
static const String wolfWolf = 'images/wolf_wolf.jpeg';
static const String sweetGrapes = 'images/sweet_grapes.jpeg';
static const String literateAndIliterate = 'images/Literate_and-_lliterate.jpeg';
}
Step 5. Create a Home Page (pages/home_page.dart).
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:storyteller/utils/images.dart';
import 'package:storyteller/pages/story_page.dart';
// HomePage is a StatelessWidget that displays a grid of images.
// Each image can be clicked to navigate to a StoryPage.
class HomePage extends StatelessWidget {
// List of image resources to be displayed in the grid.
List<String> images = [
ImageResources.sweetGrapes,
ImageResources.lionAndMouse,
ImageResources.freeBird,
ImageResources.lostAndFound,
ImageResources.elephantAndTailor,
ImageResources.wolfWolf,
ImageResources.lionAndRabbit,
ImageResources.literateAndIliterate
];
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('Storyteller'), // AppBar with the title 'Storyteller'
),
body: GridView.builder(
padding: const EdgeInsets.all(8.0), // Padding around the grid
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // number of items per row
crossAxisSpacing: 8, // spacing between items horizontally
mainAxisSpacing: 8, // spacing between items vertically
),
itemCount: images.length, // The number of items in the grid is the number of images
itemBuilder: (context, index) {
// For each item, create an InkWell widget that navigates to a StoryPage when tapped.
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StoryPage(imagePath: images[index])), // Pass the image path to the StoryPage
);
},
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(images[index]), // Display the image
fit: BoxFit.cover, // Make the image cover the entire grid item
),
borderRadius: BorderRadius.circular(10), // Round the corners of the grid items
),
),
);
},
),
);
}
}


Join the conversation! Your thoughts help the community grow.