For about a year, my "deploy process" for my portfolio site was a three-step ritual: flutter build web, cross my fingers, firebase deploy. It mostly worked, which is the dangerous part. Then one evening I shipped a build from a hotel in Abu Dhabi over Wi-Fi that dropped mid-upload, went to dinner, and left a half-deployed, blank-white-screen site live for about four hours. Nobody died. But a recruiter I'd been talking to opened the link during those four hours, and I got to explain why my personal site — the one thing on the internet I fully control — was broken.

That was the push. I moved the whole thing into GitHub Actions the next weekend. The setup below is what I've run since: build once, cache hard, get a live preview URL on every pull request, and ship to production automatically on merge. The headline is that it costs $0/month — GitHub's free Actions minutes and Firebase's free Hosting quota both cover it with room to spare — but the real win isn't the money. It's that I stopped being the single point of failure in my own deploy.

This is a complete, copy-pasteable CI/CD pipeline for Flutter web on Firebase Hosting: a GitHub Actions workflow, service-account authentication, per-PR preview channels, and dependency caching that keeps runs fast and free. Steal it, adapt it, ship.