🚀 Building a Product Recommendation App in React Native Using Google Gemini (No Backend Needed)
Generative AI is transforming how we build apps. Instead of manually coding endless rules, we can now let AI reason over data and provide context-aware answers.
In this article, I'll walk you through how I built a **React Native app **that:
Takes a user's natural-language query (e.g., "I need a lightweight laptop with long battery life")
Runs it through Google's Gemini API
Compares the query against a static product catalog
Returns personalised recommendations with explanations
All of this, without a backend - and built on snack.expo.dev so anyone can try it instantly, without worrying about dependency injection or setup.
🌟 Why This Matters
Product recommendations are everywhere - e-commerce apps, streaming platforms, food delivery.
Traditionally, they require a server-side engine with rules or ML models.
With LLMs like Gemini, we can skip the backend for quick prototypes, letting AI handle the reasoning.
By building this on Snack, anyone can fork and experiment without touching native config or setup.
This makes it possible to learn, prototype, and share quickly.
🏗️ High-Level Flow
Here’s how the system fits together:
📱 User Query +------------------+ | "Need a laptop" | +------------------+ | v 💻 React Native Frontend +---------------------------+ | TextInput + Submit Button | +---------------------------+ | v 📦 Product Catalog (JSON) +---------------------------+ | Local JSON product data | +---------------------------+ | v 🧠 Gemini API Call +---------------------------+ | Prompt + Catalog + API Key| +---------------------------+ | v 📨 Gemini Response (JSON) +---------------------------+ | Recommendations + Reasons | +---------------------------+ | v 🎨 Mobile UI Rendering +---------------------------+ | Product Cards + Why Chosen| +---------------------------+
🧩 How Gemini Works in This App
Think of Gemini as a normal API:
- Make an HTTP POST request to the Gemini endpoint.
-
Send along:
- 🔑 API Key — passed in the request URL.
- 💬 Prompt — included in the request body (user query + product catalog + output instructions).
- 📦 Headers — structured as
Content-Type: application/json
.
- Gemini processes the request and returns a structured response object.
- Since the output is strictly JSON, you can safely parse it into React Native state and render the results.
In other words:
Prompt In ---> Gemini API ---> Structured JSON Out
👉 The key takeaway: Gemini doesn't magically decide the format - you enforce it with prompt engineering ("Return JSON with fields: name, reason").
⚙️ Tech Stack
- React Native (Expo Snack) - mobile UI with zero setup.
- Google Gemini API - natural language reasoning.
- Static Product Catalog - local JSON file.
- Inline Key Management - reviewers can add their own Gemini key directly in Snack.
📂 Project Structure
/project-root
/components
ProductCard.tsx
/data
PRODUCT_CATALOG.js
/screens
HomeScreen.tsx
App.tsx
(No dependency injection required - everything runs in Snack.)
📦 Example Product Catalog
// /data/PRODUCT_CATALOG.js
export const PRODUCT_CATALOG = [
{ id: 1, name: "UltraLight Laptop", weight: "1.1kg", battery: "15h" },
{ id: 2, name: "PowerMax Pro", weight: "2.3kg", battery: "20h" },
{ id: 3, name: "BudgetBook", weight: "1.9kg", battery: "8h" },
];
🔑 Gemini API Integration
// /screens/HomeScreen.tsx
import React, { useState } from "react";
import { View, TextInput, Button, FlatList, Text } from "react-native";
import { PRODUCT_CATALOG } from "../data/PRODUCT_CATALOG";
export default function HomeScreen() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const fetchRecommendations = async () => {
const prompt = `
You are a product recommendation assistant.
Here is the product catalog:
${JSON.stringify(PRODUCT_CATALOG)}
User request: "${userQuery}"
Task:
1. Pick 2–3 products from the catalog that best match the request.
2. For each, provide:
- "name": product name
- "reason": why it matches
3. Respond ONLY in valid JSON array format.
`;
const response = await fetch(
"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=" +
"YOUR_GEMINI_API_KEY_HERE",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
contents: [{ parts: [{ text: prompt }] }],
}),
}
);
const data = await response.json();
const text = data.candidates?.[0]?.content?.parts?.[0]?.text || "[]";
setResults(JSON.parse(text));
};
return (
<View style={{ padding: 20 }}>
<TextInput
placeholder="Describe what you need..."
value={query}
onChangeText={setQuery}
style={{ borderWidth: 1, padding: 10, marginBottom: 10 }}
/>
<Button title="Get Recommendations" onPress={fetchRecommendations} />
<FlatList
data={results}
keyExtractor={(item, i) => i.toString()}
renderItem={({ item }) => (
<View style={{ marginTop: 10 }}>
<Text style={{ fontWeight: "bold" }}>{item.name}</Text>
<Text>{item.reason}</Text>
</View>
)}
/>
</View>
);
}
🎨 Sample Output
If the user types:
"I need a lightweight laptop for travel with long battery life"
Gemini might respond:
[
{
"name": "UltraLight Laptop",
"reason": "It weighs only 1.1kg and lasts 15h, perfect for travel."
},
{
"name": "PowerMax Pro",
"reason": "Though heavier, it offers 20h battery life for long trips."
}
]
And the app renders recommendation cards with reasons under each product.
📌 Key Learnings
- Gemini behaves like a standard API - you send structured input, get structured output.
- Prompt engineering is essential to enforce JSON responses.
- Frontend-only POCs are possible with Snack - no native setup, no dependency injection.
- LLMs excel at reasoning across structured data like catalogs.
🚀 What's Next?
- Add filters (price, availability).
- Secure the flow with a backend proxy for API keys.
- Extend to multi-modal catalogs (products with images + specs).
🎯 Conclusion
This project shows how quickly you can integrate Generative AI into mobile apps with Gemini.
By using snack.expo.dev, I avoided dependency injection headaches and made it super easy for anyone to fork, add their API key, and explore AI-powered recommendations.
👉 If you'd like to dive deeper into the code:
- I've hosted the full implementation in a private GitHub repository.
- You can send me a request to fork it and explore locally.
- This helps me understand how many developers are truly interested in experimenting with this project.
Top comments (0)