Your HTML/CSS/JS Site │ ▼ GitHub Repository │ │ git push triggers ▼ Cloudflare Pages (build + deploy) ├── Global CDN (300+ edge locations) ├── Automatic HTTPS (free SSL) ├── DDoS protection └── Custom domain │ ▼ yourdomain.com — live on the internet CODE_BLOCK: Your HTML/CSS/JS Site │ ▼ GitHub Repository │ │ git push triggers ▼ Cloudflare Pages (build + deploy) ├── Global CDN (300+ edge locations) ├── Automatic HTTPS (free SSL) ├── DDoS protection └── Custom domain │ ▼ yourdomain.com — live on the internet CODE_BLOCK: Your HTML/CSS/JS Site │ ▼ GitHub Repository │ │ git push triggers ▼ Cloudflare Pages (build + deploy) ├── Global CDN (300+ edge locations) ├── Automatic HTTPS (free SSL) ├── DDoS protection └── Custom domain │ ▼ yourdomain.com — live on the internet COMMAND_BLOCK: mkdir my-portfolio cd my-portfolio # Create the folder structure mkdir css js img fonts # Create your main files touch index.html css/style.css js/main.js COMMAND_BLOCK: mkdir my-portfolio cd my-portfolio # Create the folder structure mkdir css js img fonts # Create your main files touch index.html css/style.css js/main.js COMMAND_BLOCK: mkdir my-portfolio cd my-portfolio # Create the folder structure mkdir css js img fonts # Create your main files touch index.html css/style.css js/main.js CODE_BLOCK: my-portfolio/ ├── index.html ← entry point (Cloudflare Pages serves this) ├── css/ │ └── style.css ├── js/ │ └── main.js ├── img/ │ └── (your photos and project screenshots) └── fonts/ └── (any custom font files) CODE_BLOCK: my-portfolio/ ├── index.html ← entry point (Cloudflare Pages serves this) ├── css/ │ └── style.css ├── js/ │ └── main.js ├── img/ │ └── (your photos and project screenshots) └── fonts/ └── (any custom font files) CODE_BLOCK: my-portfolio/ ├── index.html ← entry point (Cloudflare Pages serves this) ├── css/ │ └── style.css ├── js/ │ └── main.js ├── img/ │ └── (your photos and project screenshots) └── fonts/ └── (any custom font files) CODE_BLOCK: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="description" content="Your Name — DevOps & Cloud Engineer" /> <title>Your Name | DevOps Engineer</title> <link rel="stylesheet" href="css/style.css" /> </head> <body> <!-- NAVIGATION --> <nav> <div class="nav-brand">Your Name</div> <ul class="nav-links"> <li><a href="#about">About</a></li> <li><a href="#projects">Projects</a></li> <li><a href="#blog">Blog</a></li> <li><a href="#contact">Contact</a></li> </ul> </nav> <!-- HERO SECTION --> <section id="hero"> <h1>Your Name</h1> <h2>DevOps & Cloud Engineer</h2> <p> Building scalable infrastructure on AWS and GCP. Kubernetes · Terraform · CI/CD · GitOps </p> <div class="hero-cta"> <a href="#projects" class="btn-primary">View Projects</a> <a href="resume.pdf" class="btn-secondary">Download Resume</a> </div> </section> <!-- ABOUT SECTION --> <section id="about"> <h2>About Me</h2> <p> Write 3–5 sentences. Who you are, what you work on, what you care about. Mention your current learning focus or the Talent Forge program. </p> </section> <!-- PROJECTS SECTION --> <section id="projects"> <h2>Projects</h2> <div class="project-grid"> <div class="project-card"> <h3>Project Title</h3> <p>Short description of what it does and the technologies used.</p> <div class="project-tags"> <span>AWS</span> <span>Terraform</span> <span>Cloudflare Pages</span> </div> <div class="project-links"> <a href="https://github.com/yourrepo">GitHub →</a> <a href="https://dev.to/yourarticle">Blog Post →</a> </div> </div> </div> </section> <!-- BLOG SECTION --> <section id="blog"> <h2>Writing</h2> <p> Links to your dev.to posts, LinkedIn articles, or any public writing. This section is proof that you build in public. </p> </section> <!-- CONTACT SECTION --> <section id="contact"> <h2>Get in Touch</h2> <p>Email: [email protected]</p> <p>LinkedIn: linkedin.com/in/yourhandle</p> <p>GitHub: github.com/yourhandle</p> </section> <script src="js/main.js"></script> </body> </html> CODE_BLOCK: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="description" content="Your Name — DevOps & Cloud Engineer" /> <title>Your Name | DevOps Engineer</title> <link rel="stylesheet" href="css/style.css" /> </head> <body> <!-- NAVIGATION --> <nav> <div class="nav-brand">Your Name</div> <ul class="nav-links"> <li><a href="#about">About</a></li> <li><a href="#projects">Projects</a></li> <li><a href="#blog">Blog</a></li> <li><a href="#contact">Contact</a></li> </ul> </nav> <!-- HERO SECTION --> <section id="hero"> <h1>Your Name</h1> <h2>DevOps & Cloud Engineer</h2> <p> Building scalable infrastructure on AWS and GCP. Kubernetes · Terraform · CI/CD · GitOps </p> <div class="hero-cta"> <a href="#projects" class="btn-primary">View Projects</a> <a href="resume.pdf" class="btn-secondary">Download Resume</a> </div> </section> <!-- ABOUT SECTION --> <section id="about"> <h2>About Me</h2> <p> Write 3–5 sentences. Who you are, what you work on, what you care about. Mention your current learning focus or the Talent Forge program. </p> </section> <!-- PROJECTS SECTION --> <section id="projects"> <h2>Projects</h2> <div class="project-grid"> <div class="project-card"> <h3>Project Title</h3> <p>Short description of what it does and the technologies used.</p> <div class="project-tags"> <span>AWS</span> <span>Terraform</span> <span>Cloudflare Pages</span> </div> <div class="project-links"> <a href="https://github.com/yourrepo">GitHub →</a> <a href="https://dev.to/yourarticle">Blog Post →</a> </div> </div> </div> </section> <!-- BLOG SECTION --> <section id="blog"> <h2>Writing</h2> <p> Links to your dev.to posts, LinkedIn articles, or any public writing. This section is proof that you build in public. </p> </section> <!-- CONTACT SECTION --> <section id="contact"> <h2>Get in Touch</h2> <p>Email: [email protected]</p> <p>LinkedIn: linkedin.com/in/yourhandle</p> <p>GitHub: github.com/yourhandle</p> </section> <script src="js/main.js"></script> </body> </html> CODE_BLOCK: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="description" content="Your Name — DevOps & Cloud Engineer" /> <title>Your Name | DevOps Engineer</title> <link rel="stylesheet" href="css/style.css" /> </head> <body> <!-- NAVIGATION --> <nav> <div class="nav-brand">Your Name</div> <ul class="nav-links"> <li><a href="#about">About</a></li> <li><a href="#projects">Projects</a></li> <li><a href="#blog">Blog</a></li> <li><a href="#contact">Contact</a></li> </ul> </nav> <!-- HERO SECTION --> <section id="hero"> <h1>Your Name</h1> <h2>DevOps & Cloud Engineer</h2> <p> Building scalable infrastructure on AWS and GCP. Kubernetes · Terraform · CI/CD · GitOps </p> <div class="hero-cta"> <a href="#projects" class="btn-primary">View Projects</a> <a href="resume.pdf" class="btn-secondary">Download Resume</a> </div> </section> <!-- ABOUT SECTION --> <section id="about"> <h2>About Me</h2> <p> Write 3–5 sentences. Who you are, what you work on, what you care about. Mention your current learning focus or the Talent Forge program. </p> </section> <!-- PROJECTS SECTION --> <section id="projects"> <h2>Projects</h2> <div class="project-grid"> <div class="project-card"> <h3>Project Title</h3> <p>Short description of what it does and the technologies used.</p> <div class="project-tags"> <span>AWS</span> <span>Terraform</span> <span>Cloudflare Pages</span> </div> <div class="project-links"> <a href="https://github.com/yourrepo">GitHub →</a> <a href="https://dev.to/yourarticle">Blog Post →</a> </div> </div> </div> </section> <!-- BLOG SECTION --> <section id="blog"> <h2>Writing</h2> <p> Links to your dev.to posts, LinkedIn articles, or any public writing. This section is proof that you build in public. </p> </section> <!-- CONTACT SECTION --> <section id="contact"> <h2>Get in Touch</h2> <p>Email: [email protected]</p> <p>LinkedIn: linkedin.com/in/yourhandle</p> <p>GitHub: github.com/yourhandle</p> </section> <script src="js/main.js"></script> </body> </html> CODE_BLOCK: /* css/style.css */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #0b0b0f; color: #e8e8f0; line-height: 1.6; } nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 5%; background: rgba(11, 11, 15, 0.95); position: sticky; top: 0; z-index: 100; border-bottom: 1px solid #1e1e2e; } .nav-brand { font-size: 1.25rem; font-weight: 700; color: #f6821f; /* Cloudflare orange */ } .nav-links { list-style: none; display: flex; gap: 2rem; } .nav-links a { color: #e8e8f0; text-decoration: none; font-size: 0.9rem; transition: color 0.2s; } .nav-links a:hover { color: #f6821f; } #hero { padding: 8rem 5% 6rem; max-width: 800px; } #hero h1 { font-size: 3.5rem; font-weight: 800; margin-bottom: 0.5rem; } #hero h2 { font-size: 1.5rem; color: #00d4ff; font-weight: 400; margin-bottom: 1.5rem; } #hero p { font-size: 1.1rem; color: #9090a8; margin-bottom: 2rem; max-width: 600px; } .hero-cta { display: flex; gap: 1rem; flex-wrap: wrap; } .btn-primary { background: #f6821f; color: #0b0b0f; padding: 0.75rem 2rem; border-radius: 4px; text-decoration: none; font-weight: 700; transition: opacity 0.2s; } .btn-primary:hover { opacity: 0.85; } .btn-secondary { border: 1px solid #f6821f; color: #f6821f; padding: 0.75rem 2rem; border-radius: 4px; text-decoration: none; font-weight: 600; } section { padding: 5rem 5%; max-width: 1200px; margin: 0 auto; } section h2 { font-size: 2rem; font-weight: 800; margin-bottom: 2rem; border-left: 4px solid #f6821f; padding-left: 1rem; } .project-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.5rem; } .project-card { background: #1a1a28; border: 1px solid #1e1e2e; border-radius: 8px; padding: 1.5rem; transition: border-color 0.2s; } .project-card:hover { border-color: #f6821f; } .project-card h3 { font-size: 1.1rem; margin-bottom: 0.75rem; } .project-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; } .project-tags span { background: rgba(246, 130, 31, 0.1); border: 1px solid rgba(246, 130, 31, 0.3); color: #f6821f; padding: 0.2rem 0.6rem; border-radius: 3px; font-size: 0.8rem; } .project-links { display: flex; gap: 1rem; margin-top: 1rem; } .project-links a { color: #f6821f; text-decoration: none; font-size: 0.9rem; } CODE_BLOCK: /* css/style.css */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #0b0b0f; color: #e8e8f0; line-height: 1.6; } nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 5%; background: rgba(11, 11, 15, 0.95); position: sticky; top: 0; z-index: 100; border-bottom: 1px solid #1e1e2e; } .nav-brand { font-size: 1.25rem; font-weight: 700; color: #f6821f; /* Cloudflare orange */ } .nav-links { list-style: none; display: flex; gap: 2rem; } .nav-links a { color: #e8e8f0; text-decoration: none; font-size: 0.9rem; transition: color 0.2s; } .nav-links a:hover { color: #f6821f; } #hero { padding: 8rem 5% 6rem; max-width: 800px; } #hero h1 { font-size: 3.5rem; font-weight: 800; margin-bottom: 0.5rem; } #hero h2 { font-size: 1.5rem; color: #00d4ff; font-weight: 400; margin-bottom: 1.5rem; } #hero p { font-size: 1.1rem; color: #9090a8; margin-bottom: 2rem; max-width: 600px; } .hero-cta { display: flex; gap: 1rem; flex-wrap: wrap; } .btn-primary { background: #f6821f; color: #0b0b0f; padding: 0.75rem 2rem; border-radius: 4px; text-decoration: none; font-weight: 700; transition: opacity 0.2s; } .btn-primary:hover { opacity: 0.85; } .btn-secondary { border: 1px solid #f6821f; color: #f6821f; padding: 0.75rem 2rem; border-radius: 4px; text-decoration: none; font-weight: 600; } section { padding: 5rem 5%; max-width: 1200px; margin: 0 auto; } section h2 { font-size: 2rem; font-weight: 800; margin-bottom: 2rem; border-left: 4px solid #f6821f; padding-left: 1rem; } .project-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.5rem; } .project-card { background: #1a1a28; border: 1px solid #1e1e2e; border-radius: 8px; padding: 1.5rem; transition: border-color 0.2s; } .project-card:hover { border-color: #f6821f; } .project-card h3 { font-size: 1.1rem; margin-bottom: 0.75rem; } .project-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; } .project-tags span { background: rgba(246, 130, 31, 0.1); border: 1px solid rgba(246, 130, 31, 0.3); color: #f6821f; padding: 0.2rem 0.6rem; border-radius: 3px; font-size: 0.8rem; } .project-links { display: flex; gap: 1rem; margin-top: 1rem; } .project-links a { color: #f6821f; text-decoration: none; font-size: 0.9rem; } CODE_BLOCK: /* css/style.css */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #0b0b0f; color: #e8e8f0; line-height: 1.6; } nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 5%; background: rgba(11, 11, 15, 0.95); position: sticky; top: 0; z-index: 100; border-bottom: 1px solid #1e1e2e; } .nav-brand { font-size: 1.25rem; font-weight: 700; color: #f6821f; /* Cloudflare orange */ } .nav-links { list-style: none; display: flex; gap: 2rem; } .nav-links a { color: #e8e8f0; text-decoration: none; font-size: 0.9rem; transition: color 0.2s; } .nav-links a:hover { color: #f6821f; } #hero { padding: 8rem 5% 6rem; max-width: 800px; } #hero h1 { font-size: 3.5rem; font-weight: 800; margin-bottom: 0.5rem; } #hero h2 { font-size: 1.5rem; color: #00d4ff; font-weight: 400; margin-bottom: 1.5rem; } #hero p { font-size: 1.1rem; color: #9090a8; margin-bottom: 2rem; max-width: 600px; } .hero-cta { display: flex; gap: 1rem; flex-wrap: wrap; } .btn-primary { background: #f6821f; color: #0b0b0f; padding: 0.75rem 2rem; border-radius: 4px; text-decoration: none; font-weight: 700; transition: opacity 0.2s; } .btn-primary:hover { opacity: 0.85; } .btn-secondary { border: 1px solid #f6821f; color: #f6821f; padding: 0.75rem 2rem; border-radius: 4px; text-decoration: none; font-weight: 600; } section { padding: 5rem 5%; max-width: 1200px; margin: 0 auto; } section h2 { font-size: 2rem; font-weight: 800; margin-bottom: 2rem; border-left: 4px solid #f6821f; padding-left: 1rem; } .project-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.5rem; } .project-card { background: #1a1a28; border: 1px solid #1e1e2e; border-radius: 8px; padding: 1.5rem; transition: border-color 0.2s; } .project-card:hover { border-color: #f6821f; } .project-card h3 { font-size: 1.1rem; margin-bottom: 0.75rem; } .project-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; } .project-tags span { background: rgba(246, 130, 31, 0.1); border: 1px solid rgba(246, 130, 31, 0.3); color: #f6821f; padding: 0.2rem 0.6rem; border-radius: 3px; font-size: 0.8rem; } .project-links { display: flex; gap: 1rem; margin-top: 1rem; } .project-links a { color: #f6821f; text-decoration: none; font-size: 0.9rem; } COMMAND_BLOCK: # Python local server (usually pre-installed) python3 -m http.server 8000 # Visit: http://localhost:8000 COMMAND_BLOCK: # Python local server (usually pre-installed) python3 -m http.server 8000 # Visit: http://localhost:8000 COMMAND_BLOCK: # Python local server (usually pre-installed) python3 -m http.server 8000 # Visit: http://localhost:8000 CODE_BLOCK: cd my-portfolio git init git add . git commit -m "feat: initial portfolio site" CODE_BLOCK: cd my-portfolio git init git add . git commit -m "feat: initial portfolio site" CODE_BLOCK: cd my-portfolio git init git add . git commit -m "feat: initial portfolio site" COMMAND_BLOCK: git remote add origin https://github.com/YOUR_USERNAME/my-portfolio.git git branch -M main git push -u origin main COMMAND_BLOCK: git remote add origin https://github.com/YOUR_USERNAME/my-portfolio.git git branch -M main git push -u origin main COMMAND_BLOCK: git remote add origin https://github.com/YOUR_USERNAME/my-portfolio.git git branch -M main git push -u origin main COMMAND_BLOCK: git log --oneline # Should show: feat: initial portfolio site COMMAND_BLOCK: git log --oneline # Should show: feat: initial portfolio site COMMAND_BLOCK: git log --oneline # Should show: feat: initial portfolio site CODE_BLOCK: aria.ns.cloudflare.com jay.ns.cloudflare.com CODE_BLOCK: aria.ns.cloudflare.com jay.ns.cloudflare.com CODE_BLOCK: aria.ns.cloudflare.com jay.ns.cloudflare.com COMMAND_BLOCK: # Check your domain's nameservers dig NS yourdomain.com +short # Expected output (Cloudflare nameservers): # aria.ns.cloudflare.com. # jay.ns.cloudflare.com. COMMAND_BLOCK: # Check your domain's nameservers dig NS yourdomain.com +short # Expected output (Cloudflare nameservers): # aria.ns.cloudflare.com. # jay.ns.cloudflare.com. COMMAND_BLOCK: # Check your domain's nameservers dig NS yourdomain.com +short # Expected output (Cloudflare nameservers): # aria.ns.cloudflare.com. # jay.ns.cloudflare.com. CODE_BLOCK: CNAME yourdomain.com → my-portfolio-abc.pages.dev (Proxied ✅) CODE_BLOCK: CNAME yourdomain.com → my-portfolio-abc.pages.dev (Proxied ✅) CODE_BLOCK: CNAME yourdomain.com → my-portfolio-abc.pages.dev (Proxied ✅) COMMAND_BLOCK: # 1. Site loads over HTTPS with Cloudflare headers curl -I https://yourdomain.com # Expected: # HTTP/2 200 # server: cloudflare # content-type: text/html; charset=utf-8 # cf-ray: <id>-<datacenter> # 2. HTTP redirects to HTTPS curl -I http://yourdomain.com # Expected: # HTTP/1.1 301 Moved Permanently # location: https://yourdomain.com/ # 3. www redirects to apex curl -I https://www.yourdomain.com # Expected: 301 to https://yourdomain.com # 4. SSL certificate is valid openssl s_client -connect yourdomain.com:443 -brief 2>/dev/null | grep -E "Verification|subject" # 5. Check which Cloudflare PoP is serving you curl -s -o /dev/null -w "Status: %{http_code} — CF-Ray: %header{cf-ray}\n" https://yourdomain.com COMMAND_BLOCK: # 1. Site loads over HTTPS with Cloudflare headers curl -I https://yourdomain.com # Expected: # HTTP/2 200 # server: cloudflare # content-type: text/html; charset=utf-8 # cf-ray: <id>-<datacenter> # 2. HTTP redirects to HTTPS curl -I http://yourdomain.com # Expected: # HTTP/1.1 301 Moved Permanently # location: https://yourdomain.com/ # 3. www redirects to apex curl -I https://www.yourdomain.com # Expected: 301 to https://yourdomain.com # 4. SSL certificate is valid openssl s_client -connect yourdomain.com:443 -brief 2>/dev/null | grep -E "Verification|subject" # 5. Check which Cloudflare PoP is serving you curl -s -o /dev/null -w "Status: %{http_code} — CF-Ray: %header{cf-ray}\n" https://yourdomain.com COMMAND_BLOCK: # 1. Site loads over HTTPS with Cloudflare headers curl -I https://yourdomain.com # Expected: # HTTP/2 200 # server: cloudflare # content-type: text/html; charset=utf-8 # cf-ray: <id>-<datacenter> # 2. HTTP redirects to HTTPS curl -I http://yourdomain.com # Expected: # HTTP/1.1 301 Moved Permanently # location: https://yourdomain.com/ # 3. www redirects to apex curl -I https://www.yourdomain.com # Expected: 301 to https://yourdomain.com # 4. SSL certificate is valid openssl s_client -connect yourdomain.com:443 -brief 2>/dev/null | grep -E "Verification|subject" # 5. Check which Cloudflare PoP is serving you curl -s -o /dev/null -w "Status: %{http_code} — CF-Ray: %header{cf-ray}\n" https://yourdomain.com COMMAND_BLOCK: # 1. Make your change locally vim index.html # add a new project, update bio, etc. # 2. Commit with a meaningful message git add . git commit -m "feat: add HashiCorp Vault HA project card" # 3. Push to GitHub git push # 4. Cloudflare Pages detects the push and deploys automatically # Monitor at: dash.cloudflare.com → Workers & Pages → your project → Deployments COMMAND_BLOCK: # 1. Make your change locally vim index.html # add a new project, update bio, etc. # 2. Commit with a meaningful message git add . git commit -m "feat: add HashiCorp Vault HA project card" # 3. Push to GitHub git push # 4. Cloudflare Pages detects the push and deploys automatically # Monitor at: dash.cloudflare.com → Workers & Pages → your project → Deployments COMMAND_BLOCK: # 1. Make your change locally vim index.html # add a new project, update bio, etc. # 2. Commit with a meaningful message git add . git commit -m "feat: add HashiCorp Vault HA project card" # 3. Push to GitHub git push # 4. Cloudflare Pages detects the push and deploys automatically # Monitor at: dash.cloudflare.com → Workers & Pages → your project → Deployments CODE_BLOCK: You (developer) │ │ git push origin main ▼ GitHub Repository (source of truth) │ │ Cloudflare Pages webhook detects push ▼ Cloudflare Pages Build Pipeline ├── Pulls latest code from GitHub ├── Runs build (instant for static HTML/CSS/JS) └── Deploys to Cloudflare edge network │ ▼ Cloudflare Edge (300+ PoPs globally) ├── Serves yourdomain.com ├── SSL/TLS — Full (strict) ├── CDN caching ├── Always-HTTPS redirect ├── DDoS protection (always-on) ├── Bot Fight Mode └── Brotli compression │ ▼ End User — fast, secure, globally distributed ✅ CODE_BLOCK: You (developer) │ │ git push origin main ▼ GitHub Repository (source of truth) │ │ Cloudflare Pages webhook detects push ▼ Cloudflare Pages Build Pipeline ├── Pulls latest code from GitHub ├── Runs build (instant for static HTML/CSS/JS) └── Deploys to Cloudflare edge network │ ▼ Cloudflare Edge (300+ PoPs globally) ├── Serves yourdomain.com ├── SSL/TLS — Full (strict) ├── CDN caching ├── Always-HTTPS redirect ├── DDoS protection (always-on) ├── Bot Fight Mode └── Brotli compression │ ▼ End User — fast, secure, globally distributed ✅ CODE_BLOCK: You (developer) │ │ git push origin main ▼ GitHub Repository (source of truth) │ │ Cloudflare Pages webhook detects push ▼ Cloudflare Pages Build Pipeline ├── Pulls latest code from GitHub ├── Runs build (instant for static HTML/CSS/JS) └── Deploys to Cloudflare edge network │ ▼ Cloudflare Edge (300+ PoPs globally) ├── Serves yourdomain.com ├── SSL/TLS — Full (strict) ├── CDN caching ├── Always-HTTPS redirect ├── DDoS protection (always-on) ├── Bot Fight Mode └── Brotli compression │ ▼ End User — fast, secure, globally distributed ✅
- You can version-control a codebase on GitHub
- You understand Cloudflare Pages, a real edge deployment platform used at scale in production
- You can configure DNS, custom domains, and SSL, skills that appear in every infrastructure job posting
- You have a working CI/CD pipeline: every git push to main triggers an automatic global deployment
- HTML, CSS, JavaScript — static site, no backend, no server
- GitHub — source control and the CI/CD trigger
- Cloudflare Pages — hosting, CDN, SSL, and deployment pipeline (all free)
- A custom domain from any registrar (Namecheap, Porkbun, Google Domains, etc.) - [ ] A GitHub account — github.com - [ ] A Cloudflare account — cloudflare.com (free plan) - [ ] A registered custom domain — around $10–12/year from any registrar - [ ] Git installed locally — git-scm.com - [ ] VS Code or any code editor
- Go to github.com/new
- Repository name: my-portfolio
- Visibility: Public
- Do NOT initialise with a README — you already have files
- Click Create repository
- Log in to cloudflare.com
- In the left sidebar, go to Workers & Pages
- Click Create → Pages tab → Connect to Git
- Click Connect GitHub
- Cloudflare opens a GitHub OAuth window
- Choose Only select repositories and select your my-portfolio repo
- Click Install & Authorize
- Pull your code from GitHub
- Run the build (instant for static files)
- Deploy to the global edge network
- Give you a URL like: https://my-portfolio-abc.pages.dev
- In the Cloudflare dashboard, click Add a Site
- Enter your domain: yourdomain.com
- Select the Free plan → Continue
- Cloudflare scans existing DNS records — review and keep any you need
- Click Continue to activation
- Find Nameservers or DNS Settings
- Replace the existing nameservers with Cloudflare's two nameservers
- Go to Workers & Pages → your Pages project
- Click the Custom domains tab
- Click Set up a custom domain
- Enter: yourdomain.com
- Click Continue
- Go to Custom domains → Set up a custom domain again
- Enter: www.yourdomain.com
- Cloudflare adds a second CNAME automatically
- Go to Rules → Redirect Rules
- Create a rule: if Hostname equals www.yourdomain.com → redirect to https://yourdomain.com (301 permanent)
- Go to your domain in Cloudflare → SSL/TLS → Overview
- Set encryption mode to Full (strict)
- SSL/TLS → Edge Certificates
- Always Use HTTPS → ON
- Automatic HTTPS Rewrites → ON
- SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS)
- Enable HSTS → set Max Age to 6 months
- Check Include subdomains if you have subdomains
- Analytics → real-time requests, bandwidth, unique visitors, cache hit ratio
- Security → threats blocked, bot traffic, firewall events
- Pages → Deployments → full deployment history, build logs, preview URLs for every branch
- One-sentence description of the problem it solves
- Technologies used — be specific: "Cloudflare Pages" not just "CDN"
- Link to the GitHub repository
- Link to your dev.to write-up if you published one
- Confirm the custom domain is activated: Workers & Pages → Custom domains → green checkmark
- Check DNS has propagated: dig yourdomain.com CNAME
- Wait 5–10 minutes and hard refresh
- Go to Deployments tab → click the failed deployment → View build log
- For a static site with no build command, the most common cause is a misconfigured output directory
- Ensure Build output directory is empty (not dist or build — those are for frameworks)
- Confirm nameservers are on Cloudflare: dig NS yourdomain.com
- Check your domain shows Active status under Websites in Cloudflare
- The domain must be active in Cloudflare before Pages custom domain recognition works
- All src= and href= attributes must use https:// or protocol-relative //
- Cloudflare's Automatic HTTPS Rewrites handles most of these automatically
- Check the Deployments tab — did the build succeed?
- Hard refresh: Ctrl + Shift + R (Windows/Linux) / Cmd + Shift + R (Mac)
- Go to Caching → Purge Everything in Cloudflare if the old version persists
- Add Cloudflare Web Analytics — Analytics → Web Analytics → add your site. Free, privacy-respecting, no cookie banner needed
- Add a contact form — Formspree or Web3Forms work without any backend
- Write your first blog post and link it from the writing section — closes the loop on building in public
- Add a Projects page — every Talent Forge project you complete gets a card here
- Project 2: Containerise a real application with Docker and deploy via a full CI/CD pipeline
- Cloudflare Pages Documentation
- Cloudflare Pages — Git Integration
- Cloudflare Pages — Custom Domains
- Cloudflare SSL/TLS Docs
- Reference Implementation: github.com/durrello/personal-website
- Live Example: durrellgemuh.com