diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000..4d202f911
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,2 @@
+/blog/** @MichaelCade
+
diff --git a/.github/PULL_REQUEST_TEMPLATE/blog_post.md b/.github/PULL_REQUEST_TEMPLATE/blog_post.md
new file mode 100644
index 000000000..987e4e6d7
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/blog_post.md
@@ -0,0 +1,13 @@
+## Blog Post Submission
+
+### Summary
+
+Describe your post in 2-4 sentences.
+
+### Checklist
+
+- [ ] I added my post under `blog/posts/` with filename format `YYYY-MM-DD-short-title.md`
+- [ ] I used the metadata schema from `blog/_template.md` (`title`, `author`, `date`, `tags`, `summary`)
+- [ ] My post is original and relevant to the 90DaysOfDevOps community topics
+- [ ] I verified local markdown links and image paths
+- [ ] I have read and followed `CONTRIBUTING.md`
diff --git a/.github/workflows/blog-post-validation.yml b/.github/workflows/blog-post-validation.yml
new file mode 100644
index 000000000..890b859a1
--- /dev/null
+++ b/.github/workflows/blog-post-validation.yml
@@ -0,0 +1,110 @@
+name: Blog Post Validation
+
+on:
+ pull_request:
+ paths:
+ - "blog/posts/*.md"
+ - "blog/_template.md"
+
+permissions:
+ contents: read
+
+jobs:
+ validate-blog-posts:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Collect changed blog posts
+ env:
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
+ run: |
+ git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'blog/posts/*.md' > changed_blog_posts.txt
+ echo "Changed posts:"
+ cat changed_blog_posts.txt || true
+
+ - name: Validate metadata and local links
+ run: |
+ python - <<'PY'
+ from pathlib import Path
+ from datetime import datetime
+ import re
+ import sys
+
+ changed_file_list = Path("changed_blog_posts.txt")
+ changed_files = []
+ if changed_file_list.exists():
+ changed_files = [line.strip() for line in changed_file_list.read_text(encoding="utf-8").splitlines() if line.strip()]
+
+ if not changed_files:
+ print("No changed blog post files detected.")
+ raise SystemExit(0)
+
+ required_fields = ["title", "author", "date", "tags", "summary"]
+ all_errors = []
+
+ for rel_path in changed_files:
+ path = Path(rel_path)
+ if not path.exists():
+ continue
+
+ text = path.read_text(encoding="utf-8")
+ lines = text.splitlines()
+ errors = []
+
+ if not lines or lines[0].strip() != "---":
+ errors.append("Missing YAML front matter opening delimiter '---'.")
+ else:
+ end_idx = None
+ for idx in range(1, len(lines)):
+ if lines[idx].strip() == "---":
+ end_idx = idx
+ break
+ if end_idx is None:
+ errors.append("Missing YAML front matter closing delimiter '---'.")
+ front_matter_lines = []
+ else:
+ front_matter_lines = lines[1:end_idx]
+
+ if end_idx is not None:
+ front_matter_text = "\n".join(front_matter_lines)
+ for field in required_fields:
+ if not re.search(rf"(?m)^{field}\s*:", front_matter_text):
+ errors.append(f"Missing required metadata field: {field}")
+
+ date_match = re.search(r'(?m)^date\s*:\s*"?(.*?)"?\s*$', front_matter_text)
+ if date_match:
+ date_value = date_match.group(1).strip()
+ try:
+ post_date = datetime.strptime(date_value, "%Y-%m-%d").date()
+ if post_date > datetime.now().date():
+ errors.append("Date cannot be in the future.")
+ except ValueError:
+ errors.append("Invalid date format. Expected YYYY-MM-DD.")
+
+ for link in re.findall(r"\[[^\]]+\]\(([^)]+)\)", text):
+ target = link.strip()
+ if not target or target.startswith(("http://", "https://", "mailto:", "#")):
+ continue
+ target = target.split("#", 1)[0].split("?", 1)[0]
+ if not target:
+ continue
+ resolved = (path.parent / target).resolve()
+ if not resolved.exists():
+ errors.append(f"Broken local link: {link}")
+
+ if errors:
+ all_errors.append(f"{rel_path}:")
+ all_errors.extend([f" - {err}" for err in errors])
+
+ if all_errors:
+ print("Validation failed:\n")
+ print("\n".join(all_errors))
+ sys.exit(1)
+
+ print("All changed blog posts passed metadata and local link validation.")
+ PY
diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
new file mode 100644
index 000000000..9ec294d63
--- /dev/null
+++ b/.github/workflows/deploy-pages.yml
@@ -0,0 +1,28 @@
+name: Deploy GitHub Pages
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+concurrency:
+ group: ${{ github.repository }}-pages
+ cancel-in-progress: false
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Deploy to gh-pages branch
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: .
+ publish_branch: gh-pages
+ exclude_assets: '.github,template_repository'
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0ff2f255c..c0b00ea2b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -38,6 +38,28 @@ To send us a pull request, please:
6. Send us a pull request, answering any default questions in the pull request.
7. Pay attention to any automated failures reported in the pull request, and stay involved in the conversation.
+## Submit a Blog Post
+
+We welcome community blog contributions for publishing on the GitHub Pages site.
+
+Please follow these requirements:
+
+1. Create your post file in `/blog/posts/` using this filename format: `YYYY-MM-DD-short-title.md`.
+2. Start from `/blog/_template.md` and include all required metadata fields:
+ - `title`
+ - `author`
+ - `date` (YYYY-MM-DD)
+ - `tags` (list)
+ - `summary`
+3. Keep content original, respectful, and relevant to DevOps, DevSecOps, platform engineering, cloud, automation, SRE, or adjacent community learning topics.
+4. Add local images under a suitable folder in the repository and use relative links.
+5. Open a pull request with the **Blog Post Submission** template and complete every checklist item.
+
+Review expectations:
+
+- Blog pull requests require maintainer review.
+- Posts may be edited or declined if they do not meet topic, originality, quality, or community standards.
+
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
diff --git a/README.md b/README.md
index 6bd307c20..7fbc14f6e 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,6 @@ The project is not a sponsored operation by any vendors and everything is access
[](https://ko-fi.com/N4N33YRCS)
-[](https://discord.gg/vqwPrNQsyK)
-

diff --git a/_sidebar.md b/_sidebar.md
index 52cf4dfa6..248f3f294 100644
--- a/_sidebar.md
+++ b/_sidebar.md
@@ -1,6 +1,8 @@
- 90DaysOfDevOps
- [2022 Version](2022.md)
- [2023 Version](2023.md)
+ - [2024 Version](2024.md)
+ - [Community Blog](blog/README.md)
- Info
- [Resources](Resources.md)
diff --git a/blog/README.md b/blog/README.md
new file mode 100644
index 000000000..ec83f7287
--- /dev/null
+++ b/blog/README.md
@@ -0,0 +1,16 @@
+# Community Blog
+
+Welcome to the 90DaysOfDevOps community blog.
+
+This section is for community-submitted posts merged through pull requests.
+
+## Blog Posts
+
+- [Welcome to the Community Blog](/blog/posts/2026-06-24-community-welcome.md)
+
+## Submit a Blog Post
+
+1. Copy the template from [`blog/_template.md`](./_template.md).
+2. Create a new file in `blog/posts/` using `YYYY-MM-DD-short-title.md`.
+3. Open a pull request using the **Blog Post Submission** template.
+
diff --git a/blog/_template.md b/blog/_template.md
new file mode 100644
index 000000000..61d11c286
--- /dev/null
+++ b/blog/_template.md
@@ -0,0 +1,13 @@
+---
+title: "Your Post Title"
+author: "Your Name"
+date: "YYYY-MM-DD"
+tags:
+ - devops
+summary: "One or two sentence summary of your post."
+---
+
+# Your Post Title
+
+Write your post here.
+
diff --git a/blog/posts/2026-06-24-community-welcome.md b/blog/posts/2026-06-24-community-welcome.md
new file mode 100644
index 000000000..26bf4382b
--- /dev/null
+++ b/blog/posts/2026-06-24-community-welcome.md
@@ -0,0 +1,16 @@
+---
+title: "Welcome to the 90DaysOfDevOps Community Blog"
+author: "90DaysOfDevOps Maintainers"
+date: "2026-06-24"
+tags:
+ - community
+ - devops
+summary: "An introduction to community blog submissions in this repository."
+---
+
+# Welcome to the 90DaysOfDevOps Community Blog
+
+This new blog section allows community members to submit practical DevOps write-ups through pull requests.
+
+Use the template in `blog/_template.md`, add your post to `blog/posts/`, and open a pull request for review.
+
diff --git a/index.html b/index.html
index 9e79507c0..02bdb31ea 100644
--- a/index.html
+++ b/index.html
@@ -8,7 +8,7 @@
-
+