<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Charli Alexender</title>
    <description>The latest articles on DEV Community by Charli Alexender (@charlialexender).</description>
    <link>https://dev.to/charlialexender</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4092702%2F77b9b372-34f9-498f-9686-12a199ab08e4.png</url>
      <title>DEV Community: Charli Alexender</title>
      <link>https://dev.to/charlialexender</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/charlialexender"/>
    <language>en</language>
    <item>
      <title>I Built an AI-Powered Portfolio with Gemini, Cloud Run, Firestore &amp; Terraform</title>
      <dc:creator>Charli Alexender</dc:creator>
      <pubDate>Tue, 08 Sep 2026 13:58:12 +0000</pubDate>
      <link>https://dev.to/charlialexender/i-built-an-ai-powered-portfolio-with-gemini-cloud-run-firestore-terraform-4j19</link>
      <guid>https://dev.to/charlialexender/i-built-an-ai-powered-portfolio-with-gemini-cloud-run-firestore-terraform-4j19</guid>
      <description>&lt;p&gt;Building a portfolio website sounds simple—until you decide to make it more than just a collection of links.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;So I decided to combine Google Cloud, Gemini, Terraform, Firestore, Cloud Run, and a React frontend into one project.&lt;/p&gt;

&lt;p&gt;Here’s how the journey went.&lt;/p&gt;

&lt;p&gt;☁️** The Architecture**&lt;/p&gt;

&lt;p&gt;The project is built around a few key components:&lt;/p&gt;

&lt;p&gt;React + Vite for the frontend&lt;br&gt;
FastAPI for the backend&lt;br&gt;
Gemini for the AI chatbot&lt;br&gt;
Firestore for portfolio data&lt;br&gt;
Google Cloud Storage for images and assets&lt;br&gt;
Cloud Run for deployment&lt;br&gt;
Terraform for infrastructure&lt;br&gt;
Cloud Build for CI/CD&lt;/p&gt;

&lt;p&gt;The goal was to keep the application simple while still making the infrastructure reproducible and scalable.&lt;/p&gt;

&lt;p&gt;🤖** Adding an AI Chatbot&lt;br&gt;
**&lt;br&gt;
One of the main features I wanted was an AI assistant that could answer questions about my portfolio.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding information into the prompt, I connected the agent to Firestore.&lt;/p&gt;

&lt;p&gt;This allows the chatbot to search my projects and articles and retrieve relevant information when answering questions.&lt;/p&gt;

&lt;p&gt;Conceptually, the agent looks like this:&lt;/p&gt;

&lt;p&gt;root_agent = Agent(&lt;br&gt;
    name="portfolio_agent",&lt;br&gt;
    model=Gemini(model=settings.model),&lt;br&gt;
    instruction=settings.system_prompt,&lt;br&gt;
    tools=[&lt;br&gt;
        search_portfolio,&lt;br&gt;
        get_content_details,&lt;br&gt;
    ],&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;This makes the chatbot much more useful than a simple static AI prompt.&lt;/p&gt;

&lt;p&gt;📚** Automatically Ingesting My Content**&lt;/p&gt;

&lt;p&gt;I also wanted to avoid manually adding every project and article to my portfolio.&lt;/p&gt;

&lt;p&gt;So I created an ingestion system that can pull content from different sources.&lt;/p&gt;

&lt;p&gt;The connectors can handle things such as:&lt;/p&gt;

&lt;p&gt;GitHub repositories&lt;br&gt;
Blog posts&lt;br&gt;
Dev.to content&lt;br&gt;
Custom portfolio entries&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The data is then normalized and stored in Firestore.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also made the ingestion process idempotent, so running it multiple times doesn't create duplicate records.&lt;br&gt;
**&lt;br&gt;
📝 Processing Blog Content with Gemini**&lt;/p&gt;

&lt;p&gt;Another interesting part was processing blog content.&lt;/p&gt;

&lt;p&gt;Instead of simply storing the title and URL, I use Gemini to generate:&lt;/p&gt;

&lt;p&gt;Short summaries&lt;br&gt;
Relevant tags&lt;br&gt;
Structured metadata&lt;/p&gt;

&lt;p&gt;This means the portfolio can display useful information without requiring me to manually write descriptions for every article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏗️ Infrastructure with Terraform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wanted the infrastructure to be reproducible, so I used Terraform rather than creating everything manually through the Google Cloud Console.&lt;/p&gt;

&lt;p&gt;Terraform manages resources such as:&lt;/p&gt;

&lt;p&gt;Cloud Run&lt;br&gt;
Firestore&lt;br&gt;
Cloud Storage&lt;br&gt;
Service accounts&lt;br&gt;
IAM permissions&lt;br&gt;
Secret Manager&lt;br&gt;
Domain mappings&lt;/p&gt;

&lt;p&gt;This makes it much easier to recreate or modify the environment later.&lt;br&gt;
**&lt;br&gt;
🚀 Deploying with Cloud Run**&lt;/p&gt;

&lt;p&gt;The application is packaged into a Docker image containing both the frontend and backend.&lt;/p&gt;

&lt;p&gt;The frontend is built first:&lt;/p&gt;

&lt;p&gt;FROM node:20-slim AS frontend-builder&lt;/p&gt;

&lt;p&gt;WORKDIR /app/frontend&lt;/p&gt;

&lt;p&gt;COPY frontend/package*.json ./&lt;br&gt;
RUN npm install&lt;/p&gt;

&lt;p&gt;COPY frontend/ ./&lt;br&gt;
RUN npm run build&lt;/p&gt;

&lt;p&gt;Then the production container runs the FastAPI application.&lt;/p&gt;

&lt;p&gt;Finally, Cloud Run handles the deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐 Secrets &amp;amp; Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn't want sensitive configuration or AI prompts sitting directly in the source code.&lt;/p&gt;

&lt;p&gt;So I used Google Secret Manager and injected the required secrets into Cloud Run as environment variables.&lt;/p&gt;

&lt;p&gt;I also added rate limiting to protect the API and reduce the risk of unexpected AI usage costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛡️ Protecting the AI Agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An AI chatbot also introduces another interesting problem: prompt injection.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This is something I think is easy to overlook when building AI applications.&lt;/p&gt;

&lt;p&gt;🎨 Building the Frontend&lt;/p&gt;

&lt;p&gt;The frontend is built with React and Vite.&lt;/p&gt;

&lt;p&gt;I wanted a clean dark-themed portfolio with sections for:&lt;/p&gt;

&lt;p&gt;Projects&lt;br&gt;
Articles&lt;br&gt;
Applications&lt;br&gt;
AI chatbot&lt;/p&gt;

&lt;p&gt;The chatbot appears as an interactive UI component so visitors can ask questions without leaving the portfolio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌐 Custom Domain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once everything was running successfully on Cloud Run, I mapped the service to my custom domain.&lt;/p&gt;

&lt;p&gt;Terraform makes this particularly straightforward because the domain mappings can also be managed as infrastructure.&lt;/p&gt;

&lt;p&gt;After the DNS configuration was updated, Google provisioned the SSL certificates automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This project taught me that building an AI application isn't just about calling an LLM API.&lt;/p&gt;

&lt;p&gt;You also need to think about:&lt;/p&gt;

&lt;p&gt;Data architecture&lt;br&gt;
Authentication and permissions&lt;br&gt;
Secrets&lt;br&gt;
Rate limiting&lt;br&gt;
Deployment&lt;br&gt;
Testing&lt;br&gt;
Prompt injection&lt;br&gt;
Infrastructure&lt;br&gt;
Monitoring&lt;br&gt;
Content ingestion&lt;/p&gt;

&lt;p&gt;The AI is only one part of the overall system.&lt;br&gt;
**&lt;br&gt;
🚀 What's Next?&lt;br&gt;
**&lt;br&gt;
There are still plenty of things I'd like to improve.&lt;/p&gt;

&lt;p&gt;Some ideas on my roadmap include:&lt;/p&gt;

&lt;p&gt;Vector search&lt;br&gt;
Better RAG capabilities&lt;br&gt;
More content sources&lt;br&gt;
Improved chatbot memory&lt;br&gt;
Better analytics&lt;br&gt;
More advanced portfolio personalization&lt;/p&gt;

&lt;p&gt;The project is still evolving, but that's what makes building it fun.&lt;br&gt;
While working on this project, I also started building a small collection of fun web-based calculators focused on love, relationships, friendship, and compatibility.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://lovescalculators.com/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Flovescalculators.com%2Fwp-content%2Fuploads%2F2025%2F12%2Flove-calculator.webp" height="500" class="m-0" width="500"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://lovescalculators.com/" rel="noopener noreferrer" class="c-link"&gt;
            Love Calculator – Love Tester &amp;amp; Percentage by Name
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Free love calculator &amp;amp; love tester in one. Enter two names for an instant love percentage, compatibility score, and relationship match – no sign-up.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Flovescalculators.com%2Fwp-content%2Fuploads%2F2025%2F12%2Flove-calculator-150x150.webp" width="150" height="150"&gt;
          lovescalculators.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It includes tools such as Love Calculator, Crush Calculator, Friendship Calculator, Soulmate Calculator, Zodiac Match, Relationship Calculator, and Love Calculator by Date of Birth.&lt;/p&gt;

&lt;p&gt;I’m continuing to experiment with new ideas and improve the tools based on how people use them. ❤️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What started as a simple portfolio idea turned into a much bigger experiment with AI, cloud infrastructure, automation, and modern web development.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;If you're building something similar, I'd love to hear about it. Share your project in the comments! 🚀&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cloud</category>
      <category>react</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
