Portfolio Website
This website is built with a self-hosted, security-focused architecture using industry-standard tools.
Astro Framework
The frontend is built using Astro, a modern static site generator that delivers lightning-fast performance by shipping zero JavaScript by default. Astro’s component-based architecture allows for clean HTML and CSS organization while supporting interactive islands where needed—in this case, embedding the Flutter web app seamlessly.
Nginx Reverse Proxy
The site is served through Nginx running on a local Debian server (aka a Raspberry Pi 4B). Nginx acts as a reverse proxy, efficiently routing requests and providing a robust layer between the internet and the backend services. This setup allows for serving multiple applications (like the portfolio site and the Movie Pitch Generator backend) from a single server with proper request handling.
Cloudflare Tunnel
Security is handled via Cloudflare Tunnels, which provides HTTPS encryption and DDoS protection without exposing the server’s IP address to the public internet. While some might argue this negates “true” self-hosting, the security benefits and simplicity of setup make it an excellent choice for personal projects requiring professional-grade protection.
Movie Pitch Generator
I really enjoy movies, so I thought a creative way to showcase both my personal interests and technical skills would be to build an interactive movie pitch generator. The app uses “Price is Right”-style spinning wheels to randomly combine genres, characters, locations, and filmmakers—then leverages AI to generate a cohesive movie pitch from the chaotic mix.
Flutter Frontend
The frontend is built with Flutter, Google’s cross-platform UI toolkit. Flutter compiles to native code for web, mobile, and desktop from a single codebase. For this project, I used flutter build web to generate the web version, which is embedded directly into the Astro site via an iframe.
Key features of the Flutter implementation include:
- Custom spinning wheel widgets with smooth animations
- Lock/unlock functionality to preserve selected values
- Responsive design that works embedded or fullscreen
Python Backend
The backend is a lightweight but robust Python API that handles the AI-powered pitch generation.
FastAPI
FastAPI powers the REST API, providing automatic OpenAPI documentation, request validation, and async support out of the box. The framework’s performance and developer experience make it ideal for AI-powered microservices.
Key endpoints:
POST /generate-pitch— Accepts wheel selections and returns an AI-generated movie pitchGET /health— Health check for monitoring
Pydantic + Pydantic AI
Pydantic handles data validation, ensuring all inputs are properly sanitized before reaching the AI model. This prevents prompt injection attacks and enforces strict limits on input sizes.
Pydantic AI is the agent framework that orchestrates the LLM interaction. It provides:
- Type-safe AI responses — The AI output is validated against a
MoviePitchschema with title, tagline, and pitch fields - Structured prompts — The agent is configured with a system prompt to act as a creative Hollywood scriptwriter
- Model flexibility — While currently using OpenAI’s GPT-4o-mini, Pydantic AI supports swapping to other LLM providers
OpenAI API
The OpenAI API provides the language model that generates the creative pitches. The GPT-4o-mini model offers a good balance of creativity, speed, and cost-effectiveness for this use case.
CORS & Security
Cross-Origin Resource Sharing (CORS) is configured to only allow requests from trusted origins (the portfolio website domain). Additional security measures include:
- Rate limiting via SlowAPI (10 requests/minute per IP)
- Security headers (X-Content-Type-Options, X-Frame-Options, X-XSS-Protection)
- Production mode that disables API documentation endpoints
- Input validation preventing oversized payloads and prompt injection