Last summer, when I found out about the Gemini API Developer Competition, I saw it as a great chance to get my hands dirty with GenAI applications. As fitness enthusiasts, we (me & Manos Chainakis) thought of creating an app that could generate personalised workout and nutrition plans—combining AI with the preferences of human coaches. That’s how Fitness Tribe AI was born. This post will walk you through the development process and the tech stack I used, with focus on the GenAI aspect.
Making Personal Training Better for Everyone, Everywhere.
ai.google.dev
The Concept Behind Fitness Tribe AI
Fitness Tribe AI combines the expertise of human coaches with the capabilities of AI models to create custom fitness programs that meet each athlete's needs and goals.
The Tech Stack
The main components of the tech stack are:
FastAPI for the backend and AI model integration
Supabase for user authentication and data management
Ionic & Angular for the frontend mobile app
Astro for the landing page
FastAPI: Backend and AI Integration
FastAPI serves as the backbone of Fitness Tribe AI, handling the AI-powered analysis.
Here’s how the project is structured:
fitness-tribe-ai/
├── app/
│ ├── main.py # Entry point for FastAPI app
│ ├── routers/ # Handles API routes (meals, nutrition, workouts)
│ ├── models/ # Manages interactions with AI models
│ ├── schemas/ # Pydantic models for input validation
│ ├── services/ # Business logic for each feature
Key elements of the FastAPI implementation:
API Routing: Routes are divided into separate files for meals (meals.py), workouts (workouts.py), and nutrition (nutrition.py), keeping the API structure organised and scalable. Each router is connected in main.py, where FastAPI’s routing system ties everything together.
Gemini Model Integration: The GeminiModel class, in gemini_model.py, handles the AI model interaction. Taking as an example the meal analyzer method, I am using Pillow to process image data, and the app sends both the image and a custom prompt to the Gemini AI to analyze meal details. An important detail here is that the prompt should be specific enough, when it comes to the format of the expected response, so that it can be processed by the service layer.
classGeminiModel:@staticmethoddefanalyze_meal(image_data):prompt=("Analyze the following meal image and provide the name of the food, ""total calorie count, and calories per ingredient...""Respond in the following JSON format:""{'food_name': '<food name>' ...}")image=Image.open(BytesIO(image_data))response=model.generate_content([prompt,image])returnresponse.text
Pydantic Schema for Data Validation: The response from the AI model is validated and structured using Pydantic models. For instance, the Meal schema in schemas/meal.py ensures the response is consistent before it is returned to the user.
Service Layer: The service layer, located in services/, encapsulates the logic of each feature. For example, the meal_service.py handles the meal analysis, ensuring the data is properly processed before returning the AI results.
fromapp.models.gemini_modelimportGeminiModelfromapp.schemas.mealimportMealfromfastapiimportHTTPExceptionimportloggingimportjsondefanalyze_meal(image_data:bytes)->Meal:try:result_text=GeminiModel.analyze_meal(image_data)ifnotresult_text:raiseHTTPException(status_code=500,detail="No response from Gemini API")clean_result_text=result_text.strip("```
json\n").strip("
```")result=json.loads(clean_result_text)returnMeal(food_name=result.get("food_name"),total_calories=result.get("total_calories"),calories_per_ingredient=result.get("calories_per_ingredient"),)exceptExceptionase:raiseHTTPException(status_code=500,detail=str(e))
By leveraging FastAPI’s modular structure, clear API routing, Pydantic for data validation, and well-organized service logic, Fitness Tribe AI efficiently handles AI model interactions with custom prompts to deliver personalized fitness and nutrition insights. You can find the full repo here:
Fitness Tribe AI is an AI-powered API, providing endpoints for coaches and athletes.
Fitness Tribe API
Fitness Tribe AI is an AI-powered fitness API designed for coaches and athletes. The API provides meal analysis functionality by analyzing meal photos and an AI powered workout builder, which can generate workout plans based on athlete profiles. Fitness Tribe AI has been built the Gemini model.
Features
Meal Analysis: Upload a photo of a meal to receive a detailed analysis of its ingredients and calorie count.
Workout Builder: Input an athlete's profile details to receive a personalized workout plan tailored to the athlete's fitness goal.
For user authentication and account management, I used Supabase, which provided a secure, scalable solution without requiring a custom-built authentication system.
Key features I leveraged:
Authentication: Supabase's built-in authentication enabled users to log in and manage their profiles with ease.
Database Management: Using Supabase’s PostgreSQL-backed database, I stored user preferences, workout routines, and meal plans to ensure updates reflected immediately in the app.
Ionic & Angular: Cross-Platform Frontend
For the frontend, I chose Ionic and Angular, which enabled me to create a mobile-first app that could be deployed on the web right away while it could also be shipped as native for both iOS and Android.
Astro: A Lightning-Fast Landing Page
For the landing page, I opted for Astro, which focuses on performance by shipping minimal JavaScript. Astro allowed me to build a fast, lightweight page that efficiently showcased the app.
Conclusion
Developing Fitness Tribe AI was a learning journey that enabled me to explore the power that AI models give us nowadays. Each framework played a role, from FastAPI’s robust backend capabilities and ease of use to Supabase’s user management, Ionic’s cross-platform frontend and Astro’s high-performance landing pages.
For anyone looking to build a GenAI app, I highly recommend exploring these frameworks (and especially FastAPI) for their powerful features and smooth developer experience.
Have questions or want to learn more about it? Let me know in the comments!