Building and Deploying AmigoGomez.com: A Complete Step-by-Step Guide
Warning
This document is an AI-generated draft derived from implementation notes.
It has not yet been fully reviewed or finalized and will be updated.
This post documents the entire end-to-end setup for building, running, and deploying AmigoGomez.com — from local development in WSL and VS Code, to CI/CD with Azure DevOps, to custom domains and HTTPS on Azure App Service.
The goal is repeatability: the same steps work locally, in the pipeline, and in production.
What You’ll End Up With
By the end of this guide, you will have:
- Local development using WSL + VS Code + uv
- A Python virtual environment in
.venv - A MkDocs static site
- A Flask app that serves the built static site
- An Azure App Service (Linux) deployment
- A working Azure DevOps pipeline
-
Custom domains configured:
-
www.amigogomez.com(canonical) amigogomez.com→ redirects towww- Optional:
.net,.org, etc. redirecting to the canonical domain - HTTPS enabled with an Azure-managed or custom certificate
- A universal redirect to enforce the canonical hostname
Recommended Repository Structure
amigogomez-site/
├── app.py
├── site/
│ ├── mkdocs.yml
│ └── docs/
├── site_out/ # generated
├── build_and_test.sh
├── pyproject.toml + uv.lock
├── azure-pipelines.yml
├── .gitignore
└── .vscode/
└── settings.json
Phase 1: Local Prerequisites
Required Tools
- Windows with WSL2
- Ubuntu installed in WSL
- VS Code
-
VS Code extensions:
-
Python
- WSL
Open the project using:
Command Palette → WSL: Open Folder in WSL…
Phase 2: Python and uv Setup
Ensure uv is installed and on your PATH.
Add this to ~/.bashrc if needed:
export PATH="$HOME/.local/bin:$PATH"
Reload:
source ~/.bashrc
Create and Sync the Virtual Environment
If using pyproject.toml:
uv sync
Phase 3: MkDocs Setup
Confirm MkDocs works:
uv run mkdocs --version
Your MkDocs project lives in site/.
Build the Static Site
From the repo root:
cd site
uv run mkdocs build --site-dir ../site_out
cd ..
This generates the static output in site_out/.
Optional: Live Authoring
cd site
uv run mkdocs serve -a 0.0.0.0:8001
Open: http://localhost:8001
Phase 4: Flask App for Static Serving
The Flask app exists solely to serve the built static site.
Key principles:
- Flask
static_folderpoints tosite_out /returnsindex.html- All other paths serve static assets
- Works identically locally and in Azure
site_out/ must exist before running the app.
Phase 5: Local Build and Test Script
Create build_and_test.sh to standardize everything:
What it should do:
- Sync Python environment
- Remove old
site_out - Build MkDocs into
site_out - Run the Flask app locally
This ensures local == CI == production.
Phase 6: VS Code Configuration
Create .vscode/settings.json:
{
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
"python.terminal.activateEnvironment": true,
"python.analysis.autoImportCompletions": true
}
Then in VS Code:
Command Palette → Python: Select Interpreter
Select:
${workspaceFolder}/.venv/bin/python
Verify:
which python
python --version
Phase 7: Azure Resources
Create or use an existing resource group.
Required Azure resources:
-
App Service Plan (Linux)
-
Basic tier or higher recommended
-
Web App for Linux
-
Python runtime
Phase 8: App Service Configuration
Startup Command
Use Gunicorn (recommended):
gunicorn --bind=0.0.0.0:$PORT app:app
App Settings
Ensure:
PORTis respected- Any redirect or environment variables are defined here
Phase 9: Azure DevOps Pipeline
Pipeline Responsibilities
Build Stage
- Checkout repo
- Install Python
- Install uv
- Install dependencies
- Build MkDocs →
site_out - Create
app.zip - Publish artifact
Deploy Stage
- Deploy ZIP to App Service
ZIP deploy / Run-From-Package is the cleanest approach.
Phase 10: Custom Domain Configuration
Canonical Domain
Canonical host:
www.amigogomez.com
DNS Records (Typical)
-
www.amigogomez.com -
CNAME →
<appname>.azurewebsites.net -
amigogomez.com(apex) -
A record → App Service IP
- TXT record for domain verification
Add both domains in:
Azure Portal → App Service → Custom domains
Phase 11: HTTPS / TLS
Option A: Azure Managed Certificate (Preferred)
- Available after domain verification
- Free and auto-renewing
Option B: Bring Your Own Certificate
- Required in some configurations
- Often stored in Azure Key Vault
Bind certificates to all hostnames you expect to serve.
Phase 12: Canonical Redirect Logic
All traffic should end up at:
https://www.amigogomez.com
Recommended location for redirects:
- Flask application code
Redirect when the request host is:
amigogomez.com<appname>.azurewebsites.net.net,.org, or any alternate domain
Use a 301 redirect, preserving path and query string.
All domains must still be added to App Service so Azure accepts the request.
Phase 13: Adding Additional Domains (.net, .org)
For each domain:
- Add DNS records (
www+ apex) - Add domain in Azure App Service
- Bind HTTPS
- Include domain in redirect logic
All alternate domains redirect to:
https://www.amigogomez.com
Phase 14: Definition of Done
Local:
build_and_test.shruns clean- Flask serves content locally
- MkDocs rebuilds correctly
Azure:
- Pipeline succeeds
- App loads at
https://www.amigogomez.com - HTTP → HTTPS enforced
- Apex domain redirects to
www - Azure default domain redirects to canonical
- TLS certificate valid
Closing Notes
This setup intentionally favors:
- Simplicity
- Predictability
- Portability
- Minimal platform lock-in
Everything is reproducible locally and debuggable without Azure.