We will cover briefly:
- Creating a Google Bard server locally
- Integrate Google Bard UI in Flutter
- Send queries/prompts from Dart (Flutter) to JS (Google Bard)
Creating a Google Bard server locally
To create our local host server, we’ll utilize NodeJS. We create a folder called server
and run
npm init -y
This creates a package.json file in the server
Next, we install the dependencies like
npm install @google-ai/generativelanguage google-auth-library express
After that, we create a file called text-prompt.js
and start writing our server-side code in it. But first, before we start programming
we require the Makersuite API key.
What is MakerSuite?

MakerSuite is a software suite or platform designed to facilitate and enhance the process of creating, designing, and prototyping various products, projects, or solutions.
Go to the Get API Key
to generate your Makersuite Key

Subsequently, you have three choices within the MakerSuite platform:
- text-based prompt,
- a data prompt,
- or a chat prompt.

Coming back to the codebase, we first import the dependencies using
import { TextServiceClient } from "@google-ai/generativelanguage";
import { GoogleAuth } from "google-auth-library";
import * as dotenv from "dotenv";
dotenv.config();
Next, we generate a file called .env
and within it, we create a variable named API_KEY
with the secretKey
obtained from the MakerSuite keys as its value.
Now, we create a text service client object using the generative AI package
const client = new TextServiceClient({
authClient: new GoogleAuth().fromAPIKey(process.env.API_KEY),
});
const generateText = async (promptString) => {
const result = await client.generateText({
model: "models/text-bison-001",
top_k: 40,
top_p: 0.95,
prompt: {
text: promptString,
},
});
return result;
};
The snippet sets up a client (TextServiceClient
) and it configures the authentication for this client using an API key stored in the API_KEY
environment variable.
We call the client.generateText
: which generates a response from the model given an input prompt.
model
: The model name to use with the format name=models/{model}
We use thetext-bison-001

top_k
: The maximum number of tokens to consider when sampling, and defaults to40
top_p
: The maximum cumulative probability of tokens to consider when sampling.prompt
: The free-form input text is given to the model as a prompt. The model will generate a TextCompletion response it predicts as the completion of the input text.
app.post("/textPrompt", async (req, res) => {
try {
const prompt = req.body.prompt;
const response = await textApi.callTextApi(prompt);
res.setHeader("Content-Type", "application/json");
let respContent = response[0]?.candidates[0]?.output;
res.status(200).send({
bot: respContent || "No output available",
});
} catch (error) {
console.error("❌ ❌ Error", error);
}
});
- Next, we set up a
POST
route/textPrompt
using Express.js We extract theprompt
property from the request’s body. - We call the
callTextApi
function, passing the extractedprompt
- We extract the data from the
response
object and send the HTTP response. If therespContent
variable has a value, it sends that as the “bot” property in a JSON response. IfrespContent
is undefined or falsy, it sends “No output available” as the “bot” property.
We listen to the incoming requests on the port 1234
Finally, we start the server by running the following command in the terminal
# LISTEN TO THE PORT
app.listen(1234, () => console.log('http://localhost:1234'))
# TO RUN THE SERVER
npm run server
We get the following:
Integrate Google Bard UI in Flutter
We start by creating a Flutter Web project
Pre-Requisite
- We should be using the flutter
master
channel - The Dart version should be
3.0.0
or above
Let’s create a project using
flutter create bard_embedding --platforms web
Note: We specify the
platform
to beweb
meaning the project only supportsweb
By default, Flutter gives us the counter app.
We include the js package in our project to enable seamless interoperability between JavaScript and Dart code. Any function in your Dart code can be annotated with a @JSExport
property using JS, allowing you to invoke it from JavaScript code.
flutter pub add js
Changes to the Counter App
Our project has only 2 dart files as shown below

We refactor the main.dart
and remove all the counterlogic. Next, we create a file called bard.dart
This contains the MyHomePage
which is a stateful widget and _MyHomePageState
is the state class for the MyHomePage
widget.
class MyHomePage extends StatefulWidget {
@override
State<MyHomePage> createState() => _MyHomePageState();
}
@js.JSExport()
class _MyHomePageState extends State<MyHomePage> {}
Next, we import the package js
and js_util
as
import 'package:js/js.dart' as js;
import 'package:js/js_util.dart' as js_util;
The _MyHomePageState
class is marked with the @JSExport
attribute because we need to make it accessible from JavaScript in order to pass user data and queries. This annotation essentially exports the Dart object _MyHomePageState
for JavaScript interaction.
In the initState
method, we invoke createDartExport
for _MyHomePageState
. This function generates a JavaScript object literal that acts as a bridge to our exported Dart class, which is _MyHomePageState
in this case.
The createDartExport()
method is used to create a JavaScript object that has a reference to a Dart object, enabling it to be used from JavaScript code. This is achieved using methods like setProperty()
and callMethod()
. These methods facilitate the setup of JavaScript properties and the invocation of JavaScript functions associated with the Dart object.
void initState() {
super.initState();
final export = js_util.createDartExport(this);
// These two are used inside the [js/js-interop.js]
js_util.setProperty(js_util.globalThis, '_appState', export);
js_util.callMethod<void>(js_util.globalThis, '_stateSet', []);
}
An exported JsObject
instance is generated by invoking the createDartExport()
function from the js_util
library. This creates a JavaScript object that has a reference to the Dart object that is being exported.
Two JavaScript properties are configured using the setProperty()
method from js_util
. The first property, _appState
, is assigned the exported object created in the previous step. This property can be accessed from JavaScript code, allowing interaction with the associated Dart object.
The second property _stateSet
represents a JavaScript function defined in js-interop.js
. This function is called using the callMethod()
method provided by js_util
. The empty array []
passed as the second argument indicates that no arguments are being passed to the function.
Note:
_appState
and_stateSet
are present inside the js file, which we will discuss later.
We create a TextEditingController
and FloatingActionButton
inside our bard.dart
Basically, this will take the user queries and pass them onto the Bard UI. There is a function that gets invoked when the user finishes the query or when the user presses the FAB
// This stores the user query
String _textQuery = '';
void textInputCallback(String value) {
textFocusNode.requestFocus();
setState(() {
_textQuery = value;
// This line makes sure the handler gets invoked
_streamController.add(null);
});
}
<script src="js/js-interop.js" defer></script>
The src
the attribute specifies the URL of the JavaScript file to be loaded, in this case js-interop.js
.

All the interop with Dart is present inside this file.
All interactions and interoperability with Dart are present within this file. We make use of IIFE to create a function.
An IIFE is a JavaScript function that is immediately executed as soon as it is defined.
(function () {
window._stateSet = function () {
console.log('HELLO From Flutter!!')
};
}());
This code sets the _stateSet
function as a property of the global window
object. Next, we access the _appState
and save it inside a variable inside the JS
let appState = window._appState;
HTML and CSS for Google Bard

Attaching the css
and html
files for Bard UI.
Send prompts from Dart (Flutter) to JS (Google Bard)
This section is split into two segments:
- Customizing the Initialization of a Flutter Web App and
- sending prompts from Dart (Flutter) to JavaScript (Google Bard)
Customizing Flutter Web App Initialization
Since we want to show the Flutter app, we create a div with ID as flutter_target
We tweak the script
tag inside the index.html
by first adding an event listener to the window
Get the div ID, which represents the flutter app
in our case flutter_target
, using the query selector
window.addEventListener("load", function (ev) {
let target = document.querySelector("#flutter_target");
_flutter.loader.loadEntrypoint({
onEntrypointLoaded: async function (engineInitializer) {
let appRunner = await engineInitializer.initializeEngine({
hostElement: target,
});
await appRunner.runApp();
},
});
});
- Using the
_flutter.loader
JavaScript API offered byflutter.js
, we modify how a Flutter app is launched on the web.
Sending prompts between Javascript and Dart
To pass the _textQuery
value from Flutter to JS, we create the textQuery
function inside of the gpt.dart
file and annotate it with the @JSExport
property (making it accessible from the JS side)
@js.JSExport()
String get textQuery => _textQuery;
JS Changes
const form = document.querySelector('form')
const chatContainer = document.querySelector('#chat_container')
const formData = new FormData(form)
We select the first form element on the page using the document.querySelector()
method. Next, we select an HTML element with an ID of chat_container
using the document.querySelector()
method.
We have a function named chatStripe()
that takes three arguments: isAi
, value
, and uniqueId
.

The
img
element’ssrc
the attribute is set to the path of thebard.svg
oruser.svg
icon depending on theisAi
argument.
The id
attribute of the message
div
is set to the uniqueId
argument.
Finally, we have a JavaScript function responsible for managing form submissions. The function is triggered when the user submits a message to the bot, either by clicking a submit button or pressing the enter key within a text input field.
Add Server
We create a POST request to a local server at http://localhost:1234/
with the user’s message as a JSON payload.
Note: The server was created in the first step above
If the response from the server is OK
, we retrieve the bot’s response from the JSON data and trim any trailing spaces or newlines using the trim()
method.
