Gemini AI FSS

Used in this guide:
Next.js 16.0.1
google/genai 1.29.0

Introduction

File Search Store (FSS) is a Gemini AI feature that lets you upload and index files so the model can search and reference their content when generating responses.

Instead of sending large documents directly in every request, you store them once in an FSS, then query Gemini to retrieve relevant information from those files making it ideal for knowledge grounding, document Q&A, or building custom AI assistants that understand your specific data.

Before we begin. Please make sure you have your Gemini API Key ready. If not, check out:

Gemini AI Basic and Run Scripts


What is Indexing?

When you upload a document to a store, Gemini runs an indexing process on the file:

  • It reads the raw byes (txt, pdf, docx, etc.).
  • Extracts text content.
  • Splits the content into chucks (segments).
  • Computes Vector embeddings and metadata for those chunks.
  • Stores those vectors and metadata in an internal index.

It results in:

  • The original file you uploaded (stored somewhere in their system).
  • The internal index representation (chunks + vectors + metadata) that Gemini uses for fast semantic search.

Note that you only see the actual file and not the internal index. “Does indexing involve creating a new file that Gemini uses instead of the doc?”. Internally, yes it creates new data structures, but not a downloadable file. It’s more like “Gemini builds a searchable representation” rather than “Gemini writes a new .txt file and uses that.”




1. Create FSS Script

This script creates both store and document at the same time.

If you want to only create the store, you'll have to modify the code and remove uploadToFileSearchStore section. I'll come back and update it later for more clarity but pretty busy right now.

root/scripts/createStore.ts
import { GoogleGenAI } from "@google/genai";
import fs from "fs";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
async function createAndUploadStore() {
    try {
        console.log("1. Creating File Search Store...");
 
        const store = await genAI.fileSearchStores.create({
            config: {
                displayName: "JakkritBio"
            }
        });
 
        const storeName = store.name;
        console.log(`Store created successfully: ${storeName}`);
 
        const filePath = './ffs-files/JakkritBio.txt';
 
        if (fs.existsSync(filePath)) {
            console.log(`2. Uploading file '${filePath}' and indexing it...`);
            await genAI.fileSearchStores.uploadToFileSearchStore({
                fileSearchStoreName: storeName!, 
                file: filePath,
            });
            console.log("File uploaded and indexed successfully.")
        }
 
    } catch (error) {
        console.error("Setup failed. Did you run this script with your GEMINI_API_KEY environment variable set?", error);
    }
}
 
createAndUploadStore();


2. Run the Script

To run the script, make sure you follow this guide: Run Scripts

If you have Run Script setup properly, you can now run:

npm run run-script -- scripts/createStore.ts

When you run this script, it connects to Gemini using your API key, creates a new File Search Store named “JakkritBio,” and saves its reference name. It then checks for the local file ./ffs-files/JakkritBio.txt; (in your Next.js project) if found, it uploads that file into the store and indexes its contents so Gemini can later search or reference the file’s data when answering questions.

After running the script you should get store name and id. You must save those data but if you lost them, you can check how to retrieve them below.




3. Retrieve Store Data (Optional)

This script assumes you know the name of the store you are looking for. If not, you can review the previous script which has your store name in it.


root/scripts/retrieveStore.ts
import { GoogleGenAI } from "@google/genai";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const TARGET_STORE = "JakkritBio";
 
async function retrieveStore() {
    
    console.log(`Searching for existing store named: ${TARGET_STORE}`);
    let foundStore = null;
    
    try {
        // get all stores
        const storeIterator = await genAI.fileSearchStores.list({});
 
        // loop and get target store
        for await (const store of storeIterator) {
            if (store.displayName === TARGET_STORE) {
                foundStore = store;
                break;
            }
        }
 
        if (foundStore) {
            const storeName = foundStore.name;
            console.log("Store Found!");
            console.log(`Display Name: ${foundStore.displayName}`);
            console.log(`Unique ID: ${storeName}`);
        } else {
            console.log(`Store with display name: ${TARGET_STORE} was not found.`)
            console.log(`Please make sure you have the correct store name`)
        }
 
    } catch (error) {
        console.error(`Operation Failed. Please check if your TARGET_STORE is set and valid`, error);
    }
}
 
retrieveStore();

Run the script:

npm run run-script -- scripts/retrieveStore.ts

3.1 List All Stores (Optional)

In case you don't remember the stores you have and you want to list them, you can run the script below:

root/scripts/listStores.ts
import { GoogleGenAI } from "@google/genai";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
async function listAllStores() {
    console.log("--- Listing All File Search Stores ---");
    let count = 0;
 
    try {
        const storeIterator = await genAI.fileSearchStores.list({});
 
        for await (const store of storeIterator) {
            count++;
            console.log(`Store #${count}:`);
            console.log(`Display Name: ${store.displayName}`);
            console.log(`Unique ID (storeName): ${store.name}`);
            console.log(`Active Documents Count: ${store.activeDocumentsCount}`);
            console.log(`Size: ${store.sizeBytes}`);
            console.log(`Updated at: ${store.updateTime}`);
            console.log(`Created at: ${store.createTime}`);
        }
 
        if (count === 0) {
            console.log("No File Search Stores found in this project.");
        } else {
            console.log(`Successfully listed ${count} store(s).`);
        }
    } catch (error) {
        console.error("Operation Failed. Please check if you have the correct API Key.", error);
    }
}
 
listAllStores();

Run the script:

npm run run-script -- scripts/listStores.ts

3.2 Delete Store (Optional)

Use this script with caution. Make sure that it's the file you truly want to delete.


root/scripts/deleteStore.ts
import { GoogleGenAI } from "@google/genai";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
// FFS_ID is the unique ID of your store that starts with "fileSearchStores/"
const STORE_TO_DELETE = process.env.FSS_ID;
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
async function deleteStore() {
 
    if (!STORE_TO_DELETE) {
        console.error("ERROR: FSS_ID environment variable is not set.");
        console.error("Please set it in your .env.local file to the store's unique ID.");
        return;
    }
 
    console.log("--- Attempting to Delete Store ---");
    console.log("Targeting Unique ID:", STORE_TO_DELETE);
 
    try {
        await genAI.fileSearchStores.delete({
            name: STORE_TO_DELETE,
            config: { force: true },
        });
 
        console.log(`Successfully deleted File Search Store: ${STORE_TO_DELETE}`);
        console.log("Tip: You can now remove this ID from your .env.local file.");
    } catch (error) {
        console.error(`Failed to delete store ${STORE_TO_DELETE}.`, error);
        console.error("Common reasons for failure: Store does not exist, or insufficient API key permissions.");
    }
}
 
deleteStore();

Run the script:

npm run run-script -- scripts/deleteStore.ts

3.3 List All Documents in Store (Optional)

root/scripts/listDocuments.ts
import { GoogleGenAI } from "@google/genai";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
const STORE_ID = process.env.FSS_ID;
const genAI  = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
async function listDocumentsInStore() {
    if (!STORE_ID) {
        console.error("ERROR: FSS_ID environment variable is not set.");
        console.error("Please set it in your .env.local file to the store's unique ID.");
        return;
    }
    console.log("--- Listing All Documents in Store ---");
    console.log(`Target Store ID: ${STORE_ID}`);
 
    let count = 0;
 
    try {
        const docIterator = await genAI.fileSearchStores.documents.list({
            parent: STORE_ID,
        });
 
        for await (const doc of docIterator) {
            count++;
            console.log(`Document #${count}`);
            console.log(`Doc ID: ${doc.name}`);
            console.log(`Display Name: ${doc.displayName}`);
            console.log(`State: ${doc.state}`);
            console.log(`Mine Type: ${doc.mimeType}`);
            console.log(`Custom Metadata: ${doc.customMetadata}`);
            console.log(`Updated at: ${doc.updateTime}`);
            console.log(`Created at: ${doc.createTime}`);
        }
 
        if (count === 0) {
            console.log("No documents found in this File Search Store");
        } else {
            console.log(`Successfully listed ${count} document(s) in the store.`);
        }
    } catch (error) {
        console.error(`Failed to list document(s) for ${STORE_ID}.`, error);
    }
}
 
listDocumentsInStore();

Run the script:

npm run run-script -- scripts/listDocuments.ts

3.4 Delete a Specific Document (Optional)

root/scripts/deleteDocument.ts
import { GoogleGenAI } from "@google/genai";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
const DOCUMENT_TO_DELETE = process.env.FSS_DOC_ID; 
 
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
async function deleteSpecificDocument() {
    
    if (!DOCUMENT_TO_DELETE) {
        console.error("ERROR: FSS_DOC_ID environment variable is not set.");
        console.error("Please set it to the document's full unique ID.");
        return;
    }
 
    console.log(`--- Attempting to Delete Specific Document ---`);
    console.log(`Targeting Name: ${DOCUMENT_TO_DELETE}`);
 
    try {
        await genAI.fileSearchStores.documents.delete({
            name: DOCUMENT_TO_DELETE,
            config: { force: true },
        });
 
        console.log(`Successfully deleted Document: ${DOCUMENT_TO_DELETE}`);
        
    } catch (error) {
        console.error(`Failed to delete document ${DOCUMENT_TO_DELETE}.`, error);
        console.error("Common reason: Document does not exist or API key permissions are insufficient.");
    }
}
 
deleteSpecificDocument();

Run the script:

npm run run-script -- scripts/deleteDocument.ts

3.5 Upload New Document (Optional)

root/scripts/uploadDocument.ts
import { GoogleGenAI } from "@google/genai";
import fs from "fs";
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
 
const STORE_ID = process.env.FSS_ID;
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
async function uploadDocumentToStore() {
    try {
 
        if (!STORE_ID) {
            console.error("ERROR: FSS_ID environment variable is not set.");
            console.error("Please set it in your .env.local file to the store's unique ID.");
            return;
        }
 
        console.log("--- Uploading Document to File Search Store ---");
        console.log(`Target Store ID: ${STORE_ID}`);
 
        const filePath = './ffs-files/JakkritBio.txt';
 
        if (fs.existsSync(filePath)) {
            console.log(`Uploading file '${filePath}' and indexing it...`);
            const res = await genAI.fileSearchStores.uploadToFileSearchStore({
                fileSearchStoreName: STORE_ID, 
                file: filePath,
            });
            console.log("File uploaded and indexed successfully.")
            console.log(`Operation Name (to track indexing status): ${res.name}`);
            console.log("Indexing is now running in the background. It may take a few minutes.");
        } else {
            console.error(`ERROR: File not found at path: ${filePath}`);
        }
 
    } catch (error) {
        console.error("Setup failed. An API error occurred.", error);
    }
}
 
uploadDocumentToStore();

Run the script:

npm run run-script -- scripts/uploadDocument.ts

JKT

Stay focused, and the rest will follow

©Jakkrit Turner. All rights reserved