AI in action: Adding AI-powered reviews in Firebase: Web Architecture & Implementation Guide
Calling frontier multimodal models directly from a web or mobile client is a security minefield if you expose raw API keys or hardcode brittle system prompts in your frontend bundle. Following the announcement of AI in action: Adding AI-powered reviews by Alexander Nohe, Jeff Huleatt on the Official Firebase Blog (2025-10-01), here is our hands-on CodingCat.dev breakdown of what actually shipped, how it works under the hood, and how we wire it into production TypeScript, Next.js, Astro, SvelteKit, React, and Angular applications. Sometimes, the best AI feature is a subtle one. In our Friendly Eats app, we wanted to automatically suggest a star rating as a user wrote their full review. This not only reduces the friction of submitting a review, but had the unexpected benefit of helping users understand how others might perceive their review.
The Mental Model: Why AI in action: Adding AI-powered reviews Matters for Web Devs
As a Google Developer Expert (GDE) for Firebase and Senior Solutions Engineer at CodingCat.dev, I evaluate every Firebase update through one lens: does it reduce boilerplate while keeping our runtime security and cloud bills predictable? Firebase AI Logic lets you invoke Gemini and Imagen models from client and edge apps using the Firebase Web SDK while keeping your API credentials off the wire, enforcing Firebase App Check, and managing server-side prompt templates centrally.
AJ Pro-Tip from Alex: Combine Firebase AI Logic with server prompt templates, Firebase Remote Config feature flags, and project spend caps so you can iterate on prompts or swap Gemini models instantly without redeploying your Next.js or Astro frontend.
How It Works: Technical Breakdown & Implementation
As the user types in the dialog, the star rating automatically updates based on the content of their review. Importantly, the suggested star rating can also be overridden, because we want the reviewer to have the final say!
Read on to see what decisions we made to implement this new feature.
Design considerations
We chose to use a client side SDK, in this case Firebase AI Logic. The primary reason that we chose to use Firebase AI Logic is to protect our Gemini API key.
Using a server side SDK will also protect the API keys, but considering that we are not pulling in massive amounts of data and are just running quick inference, we decided to settle on Firebase AI Logic.
First, Firebase AI Logic lets us use an on-device model if one is available, like Chrome’s Gemini Nano. That can help limit a significant number of calls to our Gemini API key.
Remote Gemini calls made with AI Logic go through a proxy before reaching the Gemini model endpoints. The proxy stores the API keys so that we don’t need to include our Gemini API key in the client-side code. We can then make requests to the proxy and the proxy validates your app and forwards the API keys to the appropriate endpoint (either Vertex AI with a service account or Google Generative AI with an API key).
Another feature that Firebase AI Logic provides which helps keep our endpoints secure from abuse is automatic integration with Firebase App Check to ensure that requests originating to our AI endpoints come from your app. This is done through an attestation provider like ReCaptcha Enterprise and its invisible attestation mechanism. It may add a few ms before the first request to Gemini in the app, but is otherwise seamless to the user.
Picking a model is a tradeoff between cost, speed, and quality. Normally, I start using the largest model and work my way down to the smaller models to determine whether the trade offs from a larger model to a smaller model make sense. Since we are really just asking for a small output of a star rating between 1 and 5, it’s likely that the smaller models will provide the results that we are looking for without the cost and slower performance of a larger model. If the star rating is off, we can fall back on our functionality that lets the reviewer update the rating themselves.
We narrowed down our choices to Gemini Nano from the Hybrid SDK and Gemini 2.5 Flash Lite as the fallback option. This allows us to default to the built in AI API for users on supported browsers while falling back to Gemini Flash Lite for our other users. This decision can help us keep costs down for providing this feature as there is no cost for using Gemini Nano from the Hybrid SDK and the cost of Gemini 2.5 Flash Lite is much lower than other models while providing an acceptable amount of fidelity.
We made two important decisions to design the most reliable prompt we could.
First, we used structured output so we only receive a JSON value containing the star rating back from the model. This helps prevent overly verbose responses for why a star rating was given,constraining the outputs to something that we can parse in our client code.
The second thing we did to increase the accuracy was give examples in our prompt to guide our model on what we would consider a high rating versus a low rating. This is a great way to tune responses to better fit the culture of your app’s userbase.
Based on the supplied review, translate the review
to a star rating that is equivalent:
<example>
<input>The food was wonderful and I really
enjoyed the amazing experience</input>
<output>5</output>
</example>
<example>
<input>I can say for certain I will never eat here again</input>
<output>1</output>
</example>
Input : ${userInput}We are using Firestore to store our reviews and restaurants. Firestore is secured using Firestore security rules. While our original app implementation still needed robust security rules, we did not need to change anything from the original implementation to this implementation as we are not using any new methods to update the reviews. Having said that, we think it’s important to call out what robust security rules would look like for submitting a new review, so I have included what those look like here:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// ommitting for brevity
match /restaurants/{restaurantId} {
// ommitting restaurants rules for brevity
// Ratings:
// - Authenticated user can read
// - Authenticated user can create if userId matches
// - Deletes and updates are not allowed (default)
match /ratings/{ratingId} {
allow read;
allow create: if request.auth != null
&& request.resource.data.text != ""
&& request.resource.data.rating in [1, 2, 3, 4, 5];
allow update: if request.auth != null
&& request.resource.data.userId == request.auth.uid
&& request.resource.data.text != ""
&& request.resource.data.rating in [1, 2, 3, 4, 5];
}
}
}
}Here you can see that we do place constraints on the type of reviews that can be submitted. Since we are placing a high value on the text, we make sure that the text is not null. We also want to make sure that since the rating is AI generated, if the AI happens to return a value of six or even negative one, it cannot be written to the database and instead, we can enforce that the value is within an acceptable range through this data validation call.
The code
To wrap this up, Let's break down how the actual implementation of this review component looks without all the framework considerations involved and highlight the important parts of our implementation.
To setup AI logic, we want to use the hybrid model experience where it relies on the browser model (Gemini Nano) and can fall back to the affordable flash lite model when the browser model is not available.
import
getAI,
GoogleAIBackend,
getGenerativeModel,
InferenceMode,
Schema }
import
// Your web app's Firebase configuration
const
//... Config here.
};
// Initialize Firebase
const
const
// Setup the output schema
const
properties: {
starRating: Schema.
description:
format:
}),
}
});
// setup the generative model calls.
const
mode: InferenceMode.PREFER_ON_DEVICE,
inCloudParams: {
model:
generationConfig: {
responseMimeType:
responseSchema: jsonSchema
},
},
onDeviceParams: {
promptOptions: {
responseConstraint: jsonSchema,
}
}
});Here you can see that we initialize Firebase AI logic, much the same way that we initialize other services by first getting the AI logic singleton through a call to getAI. Once we have the AI singleton, we then declare the structured output schema that we are looking to use through calling Schema.object(). This helps us define the schema and guide the model to what each value corresponds to through the use of descriptions and additionally, we can provide optional format options to further specify the format of the response value. Finally, we make a call to getGenerativeModel() which allows us to specify our options for our requests.
Since it still takes time to process the inputs into the generative model, we generally don’t want to overload the model with requests on every single key press. Instead, what we want to do is send a request after a set amount of time (500 ms or longer) from the last key press and if a new keypress has started, cancel the existing requests by cancelling the timeout request.
let
const
switch
case
case
case
case
return
default
break
}
timeoutIds.
timeoutIds
const
// Ommitted logic for generating stars here...
},
timeoutIds.
};
const
reviewBox?.Here we ignore the keys that do not change the input for requests which are the modifier keys. After we ignore those keys and return early from the handleKeyUp function, we clear the timeout using the browsers clearTimeout function and empty the list of timeouts that we are waiting on. We then start a new timeout that runs inference on the user’s input (which we will see in the next section) and add that back to the timeouts array.
Here we are actually running the code that runs inference.
const
Based on the supplied review, translate the review
to a star rating that is equivalent:
<example>
<input>The food was wonderful and I
really enjoyed the amazing experience</input>
<output>5</output>
</example>
<example>
<input>I can say for certain I will never eat here again</input>
<output>1</output>
</example>
Input :
const
result.
console.
const
console.
ratingPicker.
}).
console.
});As you can see, this is a call to generateContent from our previously defined model which we then parse the JSON for to get our structured output. Once we have that, You can call a function to update the star value In your application.
While the code snippets above show the feature in a Typescript format, we thought we would share the implementation as a react component here:
"
import
import
import
getAI,
getGenerativeModel,
GoogleAIBackend,
InferenceMode,
Schema,
}
import
// Initialize the Firebase AI Logic client SDK
const
{
// Your web app's Firebase configuration
}
);
const
// Set up the schema and model
const
properties: {
starRating: Schema.
description:
}),
},
});
const
mode: InferenceMode.PREFER_ON_DEVICE,
inCloudParams: {
model:
generationConfig: {
responseMimeType:
responseSchema: starSchema,
},
},
onDeviceParams: {
promptOptions: {
responseConstraint: starSchema,
},
},
});
// Call the generative model and return the generated star rating
async
const
Based on the supplied review, translate the review
to a star rating that is equivalent:
<example>
<input>The food was wonderful and I
really enjoyed the amazing experience</input>
<output>5</output>
</example>
<example>
<input>I can say for certain I will never eat here again</input>
<output>1</output>
</example>
Input :
`
const
const
return
}
function
let
return
clearTimeout
timer
};
}
function
const
const
const
const
()
debounce
console.
setGeneratingRating
const
setGeneratingRating
setStars
},
[]
);
useEffect
if
generateStarRating
}
}, [generateStarRating, reviewText]);
return
<>
<
id
className
value
onChange
placeholder
autoFocus
>
<
rating
setRating
setStars
/>
{generatingRating && <span>Automatically generating a rating</span>}
</>
);
}
exportexport
rating,
setRating,
}
rating
setRating
}) {
return
<
<
<
{[
<>
<
type
id
name
value
checked
onChange
/>
<
&
</
</>
))}
</
<
</
);
}Note: You’ll see we pass setRating into the Stars component. That lets reviewers override the AI suggestion if they don’t agree with it. This is an important pattern for any AI suggestion feature.
Production Web Architecture & Security Checklist
Whether we are deploying on Firebase App Hosting, Cloudflare Workers, or Vercel, shipping AI features to production requires defense-in-depth across three layers:
- Enforce Firebase App Check & Attestation: Protect your web endpoints, Cloud Functions, Data Connect GraphQL resolvers, and Firebase AI Logic calls against unauthorized replay or billing abuse using Firebase App Check with reCAPTCHA Enterprise.
- Validate Locally with the Firebase Emulator Suite: Run deterministic integration tests against local Firestore, Auth, Functions, and Data Connect PostgreSQL emulators before promoting schema or rule changes to production.
- Keep Server & Client Boundaries Type-Safe: Use the modular Firebase Web SDK and generated TypeScript bindings so SSR frameworks like Next.js, Astro, SvelteKit, and Angular serialize state cleanly without hydration flickers.
Conclusion
Accelerate your full-stack web and AI development by pairing AI in action: Adding AI-powered reviews with strict Security Rules, Firebase App Check, and local emulator testing. Come tell us on X (@CodingCatDev) and LinkedIn (CodingCat.dev) how you are using Firebase in your stack, and subscribe to the CodingCat.dev YouTube Channel so you don't miss what we build next!
Watch Our Related Firebase Video Tutorial on YouTube
Want to see how we architect and debug Firebase web applications live? Watch our related CodingCat.dev session Firebase SQL with Data Connect below, and make sure to Subscribe to CodingCat.dev on YouTube for weekly full-stack web and AI deep dives:
Resources, Official Docs & Related CodingCat.dev Guides
- Primary Release Source: AI in action: Adding AI-powered reviews on the Official Firebase Blog (published 2025-10-01 by Alexander Nohe, Jeff Huleatt)
- Official Firebase Documentation: Firebase Developer Docs & Web SDK Reference
- Related on CodingCat.dev: Unlocking Dynamic Experiences with Client-Side custom signals conditions in Firebase Remote Config
- Related on CodingCat.dev: Data Connect: get started faster and have more data control
- Related on CodingCat.dev: Firebase SQL with Data Connect
- Related on CodingCat.dev: Build a Custom No-Code App in 90 Minutes
Frequently Asked Questions (FAQ)
What are the key capabilities introduced in AI in action: Adding AI-powered reviews?
AI in action: Adding AI-powered reviews (announced 2025-10-01 by the Firebase team) enhances the platform for Firebase, Google Cloud, Web Dev, AI, React, TypeScript, Security workloads. Sometimes, the best AI feature is a subtle one. In our Friendly Eats app, we wanted to automatically suggest a star rating as a user wrote their full review. This not only reduces the friction of submitting a review, but had the unexpected benefit of helping users understand how others might perceive their review. Developers can review the primary announcement on the Firebase Blog alongside our implementation patterns and production checklist above.
How do web developers use AI in action: Adding AI-powered reviews with Next.js, SvelteKit, React, or Angular?
Web developers can integrate these features using the modular Firebase JavaScript/TypeScript SDK, Firebase Data Connect web bindings, and Firebase App Hosting. Always pair client-side SDK initialization with Firebase App Check and strict Security Rules, and test locally with the Firebase Local Emulator Suite before deploying.
Where can I watch video tutorials on Firebase Web and AI development?
You can watch our hands-on Firebase video walkthroughs on the CodingCat.dev YouTube Channel, including Firebase SQL with Data Connect, and follow us on X (@CodingCatDev) for weekly full-stack tutorials.