Project 01: Static Site on Google Cloud
Purpose
Build and deploy the Cloud Engineer documentation site as a static website hosted on Google Cloud using Firebase Hosting.
This project turns a Markdown-based documentation site into a real cloud-hosted portfolio asset. The goal is not just to publish pages. The goal is to practice the work behind cloud delivery: local builds, hosting configuration, custom DNS, organization-policy troubleshooting, deployment discipline, and fallback planning.
Scenario
Assume you need to publish a lightweight documentation, portfolio, or informational site without maintaining servers. The site is built from Markdown using MkDocs Material, deployed as static files, and served through a managed Google Cloud hosting service.
The final public site is intended to be available at:
https://cloudengineer.mcqueencloud.com/
A default Firebase Hosting URL remains available as a fallback.
This is a good first Google Cloud project because it introduces cloud hosting, DNS, IAM, organization policy, deployment artifacts, and public delivery without requiring application servers, containers, or Kubernetes.
Final Architecture
Markdown source files
-> MkDocs Material build
-> generated site/ directory
-> Firebase Hosting
-> Squarespace DNS CNAME
-> cloudengineer.mcqueencloud.com
Services and Tools Used
- Firebase Hosting
- IAM and Service Accounts
- Cloud Monitoring
- MkDocs Material
- GitHub
- Squarespace DNS
If firebase-hosting.md does not exist yet in the Google Cloud services section, add it later. Firebase Hosting is the actual Google Cloud-backed hosting service used in this implementation.
What Was Built
- A MkDocs Material documentation site.
- A separate GCP-hosted site repository.
- A Firebase project connected to a Google Cloud project.
- Firebase Hosting configured to serve the generated
site/directory. - A custom subdomain:
cloudengineer.mcqueencloud.com. - A Squarespace DNS CNAME record pointing the subdomain to Firebase Hosting.
- A GitHub Pages fallback strategy for future cost or availability concerns.
- A cleaner
.gitignoreto avoid committing generated build artifacts and Firebase local cache files.
Why Firebase Hosting Was Used
Firebase Hosting was chosen because it is a managed static hosting option backed by Google Cloud. For a static documentation site, it provides a simpler path than manually building a Cloud Storage bucket, HTTPS load balancer, managed certificate, and CDN configuration.
Firebase Hosting is a strong first implementation because it handles several production-facing concerns with less operational overhead:
- static asset hosting,
- HTTPS support,
- custom domain support,
- simple CLI deployment,
- predictable deployment workflow,
- low infrastructure complexity.
This project may later be extended with a more infrastructure-heavy implementation using Cloud Storage, Cloud Load Balancing, Cloud CDN, and managed certificates. The Firebase version is the practical first deployment path.
Implementation Steps
1. Create the GCP-hosted site repository
A separate repository was created for the GCP-hosted implementation.
The original documentation site remained useful as a starting point, but the new repository became the source for the Firebase-hosted version.
The new repo copied the MkDocs project structure:
docs/
mkdocs.yml
requirements.txt
README.md
.gitignore
LICENSE
The generated MkDocs output folder was intentionally not treated as source:
site/
2. Update MkDocs metadata
The mkdocs.yml file was updated so the site points to the planned custom domain:
site_url: https://cloudengineer.mcqueencloud.com/
The repository metadata was also updated to reflect the GCP-hosted repository.
3. Build the MkDocs site locally
The local build process used a Python virtual environment.
.venv\Scripts\activate
mkdocs build --strict
The strict build confirmed that the documentation source could be converted into static site output without broken navigation or missing files.
4. Install and authenticate the Firebase CLI
Firebase Hosting required the Firebase CLI.
The first issue was that npm was not recognized, which meant Node.js was not installed or was not available on the Windows PATH.
The resolution was to install Node.js LTS, reopen the terminal, and confirm:
node -v
npm -v
Then Firebase CLI was installed globally:
npm install -g firebase-tools
The CLI authentication was completed with:
firebase login
5. Create and prepare the Google Cloud project
A Google Cloud project was created for the site.
The working project ID became:
cloud-engineer-site-496219
The project was intended to support the Firebase-hosted static site.
6. Troubleshoot Firebase project attachment
The first major deployment blocker occurred when trying to add Firebase to the Google Cloud project.
The Firebase CLI returned:
Error: Failed to add Firebase to Google Cloud Platform project.
The debug log showed that the Firebase addFirebase API call failed with:
403 PERMISSION_DENIED
The caller does not have permission
This required several checks and fixes.
Issue: Domain Restricted Sharing organization policy
The Google Cloud organization had the legacy Domain Restricted Sharing policy enabled:
constraints/iam.allowedPolicyMemberDomains
This policy can block IAM principals outside the allowed domain from being added. That matters because Firebase may need to add Google-managed service agents or service identities to the project.
The project-level policy was reviewed and overridden for the specific Cloud Engineer Site project. The effective policy was changed to:
Allowed: All
This kept the exception scoped to the project rather than weakening the entire organization.
Issue: Required APIs were not enabled
The following APIs were enabled on the project:
Firebase Management API
Firebase Hosting API
Cloud Resource Manager API
Service Usage API
These APIs were needed for Firebase setup and hosting management.
Issue: Firebase Terms of Service
Firebase setup still failed after IAM and policy changes. A dummy Firebase project was created from the Firebase Console so the Firebase Terms of Service could be accepted in the browser.
This mattered because Firebase Terms acceptance cannot always be completed through the CLI flow.
Issue: stale authentication/session state
After the policy changes, API enablement, and Terms acceptance, the Firebase CLI still failed until the Firebase CLI session was refreshed.
The resolution was:
firebase logout
firebase login
After logging out and logging back in, Firebase setup succeeded.
7. Initialize Firebase Hosting
Firebase Hosting was initialized from the repository root:
firebase init hosting
The selected setup was:
Hosting only
Use an existing Firebase project
Public directory: site
Configure as a single-page app: No
Set up automatic GitHub deploys: No
Overwrite index.html: No
Firebase created the hosting configuration files:
firebase.json
.firebaserc
The important hosting setting is that Firebase serves the generated MkDocs output from:
site
8. Deploy to Firebase Hosting
The site was built and deployed manually:
mkdocs build --strict
firebase deploy --only hosting
Firebase provided a default hosting URL first. That confirmed the static site could be served successfully before custom domain setup.
9. Configure the custom domain
The preferred domain was:
cloudengineer.mcqueencloud.com
In Firebase Hosting, a custom domain was added for the subdomain.
Firebase provided this DNS record:
Type: CNAME
Domain name: cloudengineer.mcqueencloud.com
Value: cloud-engineer-site-496219.web.app
Because the DNS provider was Squarespace, the custom DNS record was entered as:
Type: CNAME
Host: cloudengineer
Value: cloud-engineer-site-496219.web.app
After DNS propagation and Firebase verification, the custom domain worked.
10. Update .gitignore
The generated site files and Firebase local cache files should not be committed.
The .gitignore was updated to include:
# MkDocs build output
site/
# Firebase local/cache files
.firebase/
# Firebase debug logs
firebase-debug.log
firebase-debug.*.log
This prevents accidental commits of generated files such as:
site/index.html
site/sitemap.xml
site/assets/
.firebase/hosting.*.cache
11. Preserve a GitHub Pages fallback strategy
The original GitHub Pages deployment was unpublished to prevent two public versions from drifting apart.
The plan is to make the GCP-hosted repository the source of truth and eventually deploy the same MkDocs source to two targets:
Firebase Hosting -> primary custom domain
GitHub Pages -> free fallback URL
That keeps one documentation source while preserving a no-cost fallback if Firebase hosting is paused later.
Issues and Resolutions
| Issue | Cause | Resolution |
|---|---|---|
npm was not recognized |
Node.js was not installed or not on PATH | Installed Node.js LTS and reopened the terminal |
| Firebase project setup failed | Firebase could not attach to the GCP project | Reviewed IAM, org policy, APIs, Terms, and CLI auth |
403 PERMISSION_DENIED on addFirebase |
Initially appeared to be IAM, but also involved org policy/API/session state | Granted appropriate project roles, enabled APIs, accepted Firebase Terms, refreshed CLI login |
| Domain Restricted Sharing blocked setup | Organization policy restricted allowed IAM principals | Added a project-level override with Allowed: All for this specific project |
| Required Firebase APIs were missing | APIs were not enabled on the project | Enabled Firebase Management API, Firebase Hosting API, Cloud Resource Manager API, and Service Usage API |
| Firebase setup still failed after fixes | Firebase CLI auth/session state was stale | Ran firebase logout and firebase login |
| Generated files appeared in Git changes | mkdocs build and Firebase deploy created local artifacts |
Updated .gitignore to exclude site/, .firebase/, and Firebase debug logs |
| Default Firebase URL was not the desired public URL | Firebase Hosting creates a default URL first | Added cloudengineer.mcqueencloud.com as a custom domain and configured Squarespace DNS |
Security and Operations Considerations
This project is simple, but it still includes real cloud engineering concerns.
Access control
Write access to the repository and Firebase project should remain limited. Deployment rights should not be granted broadly just because the site is public.
Organization policy
The Domain Restricted Sharing exception should remain scoped to the static site project. The organization-wide policy should not be weakened globally just to support one hosting project.
Build artifacts
The site/ directory is generated output. It should be rebuilt during deployment rather than committed to source control.
Custom domain ownership
DNS records should be controlled through the domain provider. For this project, Squarespace manages DNS for mcqueencloud.com.
Deployment model
Deployment is currently manual:
mkdocs build --strict
firebase deploy --only hosting
A future improvement is to automate Firebase deployment with GitHub Actions after the manual process is stable.
Cost Considerations
Firebase Hosting should be low cost for a small static documentation site, but the project should still be monitored.
Potential cost drivers include:
- storage usage,
- bandwidth/egress,
- build or deployment automation,
- future use of additional Firebase or Google Cloud services.
A no-cost GitHub Pages fallback is useful if the hosted custom-domain version is paused later.
How to Extend This Project
- Add a GitHub Actions workflow for Firebase Hosting deployment.
- Add a GitHub Pages fallback workflow from the same repository.
- Add a staging channel using Firebase Hosting preview channels.
- Add uptime monitoring for the custom domain.
- Add a project architecture diagram.
- Add a short architecture decision record explaining why Firebase Hosting was chosen over Cloud Storage static hosting.
- Add a Cloud Storage + Load Balancer version as an advanced alternative.
Portfolio Value
This project shows more than basic static hosting.
It demonstrates the ability to:
- build a technical documentation site from Markdown,
- configure a managed Google Cloud hosting service,
- troubleshoot IAM and organization policy issues,
- enable required APIs,
- configure custom DNS through an external registrar/DNS provider,
- separate source files from generated build artifacts,
- document the deployment process clearly,
- preserve a fallback hosting strategy.
That makes it a useful first cloud engineering portfolio project because it combines content, deployment, governance, DNS, and operational discipline.
Official References
- Firebase Hosting documentation
- Firebase Hosting custom domains
- Firebase CLI reference
- Use Firebase with existing Google Cloud projects
- Google Cloud Domain Restricted Sharing
- Google Cloud Organization Policy Service
- Google Cloud Service Usage documentation
- MkDocs documentation
- MkDocs Material documentation