Building a portfolio website sounds simple—until you decide to make it more than just a collection of links.
I wanted to build a portfolio that could automatically collect my projects and articles, store them in the cloud, and let visitors interact with an AI-powered chatbot.
So I decided to combine Google Cloud, Gemini, Terraform, Firestore, Cloud Run, and a React frontend into one project.
Here’s how the journey went.
☁️** The Architecture**
The project is built around a few key components:
React + Vite for the frontend
FastAPI for the backend
Gemini for the AI chatbot
Firestore for portfolio data
Google Cloud Storage for images and assets
Cloud Run for deployment
Terraform for infrastructure
Cloud Build for CI/CD
The goal was to keep the application simple while still making the infrastructure reproducible and scalable.
🤖** Adding an AI Chatbot
**
One of the main features I wanted was an AI assistant that could answer questions about my portfolio.
Instead of hardcoding information into the prompt, I connected the agent to Firestore.
This allows the chatbot to search my projects and articles and retrieve relevant information when answering questions.
Conceptually, the agent looks like this:
root_agent = Agent(
name="portfolio_agent",
model=Gemini(model=settings.model),
instruction=settings.system_prompt,
tools=[
search_portfolio,
get_content_details,
],
)
This makes the chatbot much more useful than a simple static AI prompt.
📚** Automatically Ingesting My Content**
I also wanted to avoid manually adding every project and article to my portfolio.
So I created an ingestion system that can pull content from different sources.
The connectors can handle things such as:
GitHub repositories
Blog posts
Dev.to content
Custom portfolio entries
The data is then normalized and stored in Firestore.
I also made the ingestion process idempotent, so running it multiple times doesn't create duplicate records.
**
📝 Processing Blog Content with Gemini**
Another interesting part was processing blog content.
Instead of simply storing the title and URL, I use Gemini to generate:
Short summaries
Relevant tags
Structured metadata
This means the portfolio can display useful information without requiring me to manually write descriptions for every article.
🏗️ Infrastructure with Terraform
I wanted the infrastructure to be reproducible, so I used Terraform rather than creating everything manually through the Google Cloud Console.
Terraform manages resources such as:
Cloud Run
Firestore
Cloud Storage
Service accounts
IAM permissions
Secret Manager
Domain mappings
This makes it much easier to recreate or modify the environment later.
**
🚀 Deploying with Cloud Run**
The application is packaged into a Docker image containing both the frontend and backend.
The frontend is built first:
FROM node:20-slim AS frontend-builder
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm install
COPY frontend/ ./
RUN npm run build
Then the production container runs the FastAPI application.
Finally, Cloud Run handles the deployment.
🔐 Secrets & Security
I didn't want sensitive configuration or AI prompts sitting directly in the source code.
So I used Google Secret Manager and injected the required secrets into Cloud Run as environment variables.
I also added rate limiting to protect the API and reduce the risk of unexpected AI usage costs.
🛡️ Protecting the AI Agent
An AI chatbot also introduces another interesting problem: prompt injection.
Since users can send arbitrary input to the chatbot, I added defensive checks and tests to make sure users cannot easily manipulate the agent into ignoring its intended behavior.
This is something I think is easy to overlook when building AI applications.
🎨 Building the Frontend
The frontend is built with React and Vite.
I wanted a clean dark-themed portfolio with sections for:
Projects
Articles
Applications
AI chatbot
The chatbot appears as an interactive UI component so visitors can ask questions without leaving the portfolio.
🌐 Custom Domain
Once everything was running successfully on Cloud Run, I mapped the service to my custom domain.
Terraform makes this particularly straightforward because the domain mappings can also be managed as infrastructure.
After the DNS configuration was updated, Google provisioned the SSL certificates automatically.
💡 What I Learned
This project taught me that building an AI application isn't just about calling an LLM API.
You also need to think about:
Data architecture
Authentication and permissions
Secrets
Rate limiting
Deployment
Testing
Prompt injection
Infrastructure
Monitoring
Content ingestion
The AI is only one part of the overall system.
**
🚀 What's Next?
**
There are still plenty of things I'd like to improve.
Some ideas on my roadmap include:
Vector search
Better RAG capabilities
More content sources
Improved chatbot memory
Better analytics
More advanced portfolio personalization
The project is still evolving, but that's what makes building it fun.
While working on this project, I also started building a small collection of fun web-based calculators focused on love, relationships, friendship, and compatibility.
The idea is to create simple tools that people can use instantly without complicated setup or registration. You can explore the project and try the different calculators here:
It includes tools such as Love Calculator, Crush Calculator, Friendship Calculator, Soulmate Calculator, Zodiac Match, Relationship Calculator, and Love Calculator by Date of Birth.
I’m continuing to experiment with new ideas and improve the tools based on how people use them. ❤️
Final Thoughts
What started as a simple portfolio idea turned into a much bigger experiment with AI, cloud infrastructure, automation, and modern web development.
The most interesting part wasn't any individual technology—it was seeing how all of these pieces could work together to create something genuinely useful.
If you're building something similar, I'd love to hear about it. Share your project in the comments! 🚀
lovescalculators.com
Top comments (1)
The approach of connecting the AI chatbot to Firestore for dynamic responses is a clever way to enhance user interaction, making your portfolio not just a showcase but a living resource. I appreciate how you’ve implemented idempotency in the ingestion process to avoid duplicates—such attention to detail is vital for maintaining data integrity. If you're considering expanding the ingestion system or implementing additional features like advanced analytics on user interactions, I’d be happy to discuss a paid collaboration to support that effort. What challenges have you faced with managing the integration between the different services?