Gemini 3 flash is a generative ai designed by Google for tasks that require high speed and efficiency. It is a large language model often used with prompt engineering to improve its performance. This tutorial is aimed at walking you through on how to integrate gemini 3 flash preview. Required Technologies:
- JavaScript
- Node.js APIs
- Mongodb, mongoose
Here is a step by step guide to follow:
Step 1: Download and install node.js. visit node.js official website here
then also initialize node using
npm init -y
This initializes your node js application with a '-y' flag i.e a yes to all the prompts
Step 2: Visit gemini api docs and get your free api key. here
You can rename the api to 'apiKey'
Then create a dotenv file and paste it as follows
GEMINI_API_KEY = the-api-key-from-above-here
Step 3: Install the necessary packages using npm(node package manager)
npm i @google/genai bcryptjs connect-mongo cors dotenv express express-session mongoose nodemon
where :
@google/genai is the gemini ai installation
bcryptjs is used for password hashing before storing in the database
connect-mongo is used to persist session in the mongodb database as against memory
cors(Cross-Origin Resource Sharing) helps us to make requests to the backend from another domain
dotenv helps us access secret information in our environment variable file e.g GEMINI_API_KEY. and it goes like this process.env.GEMINI_API_KEY
express is a library for routing, middleware, request and response etc
express-session is the standard middleware for managing user sessions in Express.js.
Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js.
nodemon is a node monitor. It monitors files for changes and refreshes automatically.
Quickly make some changes in your package.json file
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
}
To use nodemon run :
npm run dev
Step 4: sign up to mongodb atlas for a free connection string here
You can actually use any database of your choice
Step 5: Database Schema for users and chats
A schema defines the structure of documents in a MongoDB collection.
// User Schema:
const mongoose = require('mongoose')
const userSchema = mongoose.Schema({
name:{
type:String,
required:[true,"user name is required"],
trim: true
},
email:{
type:String,
required:[true,"user email is required"],
unique: true, // Prevents duplicate accounts
lowercase: true, // Converts email to lowercase
trim: true
},
password:{
type:String,
required:[true,"user password is required"]
},
},{timestamps:true})
const User = mongoose.model('User',userSchema)
module.exports = User
// Chat Schema
const mongoose = require('mongoose')
const ChatSchema = new mongoose.Schema({
userId:{type:mongoose.Schema.Types.ObjectId, ref:'User'},
// use an array of objects to store the conversation flow
messages:[{
role:{type:String,enum:['user','model'],required:true},
parts:{type:String,required:true},
timestamp:{type:Date,default:Date.now}
}],
// New: Store a short bio/summary of what the user like
})
const Chat = mongoose.model('Chat',ChatSchema)
module.exports = Chat
Step 6: Connect to the database
// config/db.js
const mongoose = require('mongoose')
const connectDB = async()=>{
try {
const conn = await mongoose.connect(process.env.MONGODB_URI)
console.log(`Connected: ${conn.connection.host} ${conn.connection.name}`)
} catch (error) {
console.log(error.message)
}
}
module.exports = connectDB
Step 7: At this point, let's see folders and modules
// controllers/userController.js
const User = require('../models/userModel')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
// Register user
exports.register = async(req,res)=>{
// getting user details from the html or api tester
const {name,email,password} = req.body
//check if email exists
const isUser = await User.findOne({email})
if(isUser){
return res.send('User already exists')
}
// hashing the password
const hashedPassword = await bcrypt.hash(password,10)
// bundling user info to be saved on the database
const user = new User({
name:name,
email:email,
password:hashedPassword
})
try {
// save user
const newUser = await user.save()
if(!newUser){
res.status(401).json({msg:"Sorry, we could not register user"})
}
// return the new user to the frontend
res.status(201).json({newUser})
} catch (error) {
res.send(error.message)
}
}
// login logic
exports.login = async (req, res) => {
// getting user inputs from the html forms or api testers(e.g postman)
const { email, password } = req.body;
try {
// checking if user exists
const user = await User.findOne({ email });
if (!user) return res.status(404).json({ message: "User not found" });
// comparing the password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(401).json({ message: "Invalid credentials" });
// Set the session
req.session.userId = user._id.toString();
// Explicitly save the session before sending the response
req.session.save((err) => {
if (err) return res.status(500).json({ message: "Session save failed" });
return res.status(200).json({ msg: 'Logged in successfully!' });
});
} catch (error) {
res.status(500).json({ message: error.message });
}
};
exports.logout = async(req,res)=>{
res.session.destroy(err=>{
if(err){
return res.status(500).json({msg:"Logout failed"})
}
res.clearCookie('connect.sid')
res.status(200).json({msg:'Logded out'})
})
}
// controllers/chatController.js
const Chat = require('../models/chatModel')
const User = require('../models/userModel')
// import { GoogleGenAI } from "@google/genai";
const {GoogleGenAI} = require('@google/genai')
/**
- This line of code is the initialization step for using Google’s generative AI models
- (like Gemini 3 Flash) in a Node.js application.
- It effectively "unlocks" the library so your code can talk to Google's servers.
*/
const ai = new GoogleGenAI({
apiKey: process.env.GEMINI_API_KEY, // Access the key securely
});
// Create chat
exports.chat = async (req, res) => {
try {
const userId = req.session.userId; // This comes from the frontend. Sends to your browser upon login
// checking if user exists
if (!userId) {
return res.status(401).json({ message: "Not logged in" });
}
// 1. Fetch previous memory
const chatData = await Chat.findOne({ userId });
// javaScript ternary operator. if 'chatData' above has value,get the message property. empty array if none
const history = chatData ? chatData.messages : [];
// 2. Format for Gemini (with safety filter)
const context = history
.filter(msg => msg.parts && msg.parts.trim() !== "") // Remove empty messages
.map(msg => ({
role: msg.role === "model" ? "model" : "user", // Ensure role is exactly right
parts: [{ text: msg.parts }]
}));
// 3. Add new user message (with safety check)
const userPrompt = req.body.prompt;
if (!userPrompt || userPrompt.trim() === "") {
return res.status(400).json({ error: "Prompt cannot be empty" });
}
context.push({
role: "user",
parts: [{ text: userPrompt }]
});
// 4. Send to AI
const response = await ai.models.generateContent({
model: "gemini-3-flash-preview",
contents: context
});
const aiReply = response.text;
// 5. Save only last exchange
await Chat.findOneAndUpdate(
{ userId },
{
$push: {
messages: {
$each: [
{ role: "user", parts: req.body.prompt },
{ role: "model", parts: aiReply }
],
$slice: -20
}
}
},
{ upsert: true, new: true }
);
// return res.send([{user:req.body.prompt,model:aiReply}]);
const info = await Chat.findOne({userId})
res.send(info.messages)
} catch (error) {
// console.error(error);
res.status(500).json({ error: error.message });
}
};
// Get user chat
exports.getChat = async(req,res)=>{
const userId = req.session.userId;
if(!userId) return res.send("You must be logged in")
try {
const info = await Chat.findOne({userId})
if(!info){
res.send("User info not found")
}else{
res.send(info.messages)
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
// routes/ userRoute.js
const { register, login, logout } = require("../controllers/userController");
const express = require('express')
const router = express.Router()
router.post('/register',register);
router.post('/login',login)
router.post('/logout',logout)
module.exports = router
// routes/chatRoute.js
const { chat, getChat } = require("../controllers/chatController");
const express = require('express')
const router = express.Router()
router.post('/api/chat',chat)
router.get('/api/chat',getChat)
module.exports = router
// app.js
const express = require('express')
const dotenv = require('dotenv').config()
const session = require('express-session')
const MongoStore = require('connect-mongo').default
const connectDB = require('./config/db')
const UserRoutes = require('./routes/userRoute')
const ChatRoute = require('./routes/chatRoute')
const cors = require('cors')
const app = express()
app.set("trust proxy", 1);
connectDB()
app.use(express.json())
// app.use(cors())
app.use(cors({
origin: 'https://domain.com', // Replace with your actual frontend URL
credentials: true
}));
app.use(express.urlencoded({extended:false}))
// app.set("trust proxy", 1);
app.use(session({
name: "sid",
secret: process.env.SESSION_SECRET_KEY,
resave: false,
saveUninitialized: false,
store: MongoStore.create({
mongoUrl: process.env.MONGODB_URI,
collectionName: 'sessions',
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24,
httpOnly: true,
secure: true,
sameSite: "none"
}
}));
app.use('/api/auth',UserRoutes)
app.use('/',ChatRoute)
app.get('/',(req,res)=>{
res.send('Hello AI')
})
const port = process.env.PORT || 7000
app.listen(port,()=>{
console.log(`http://localhost:${port}`)
})
Thanks for taking out your time to read this. Please try something. Build something. Break something
follow my youTube channel for tutorials