How I Built My Personal Blog with GitHub Copilot and Hosted It on GitHub Pages

How I Built My Personal Blog with GitHub Copilot and Hosted It on GitHub Pages

A behind-the-scenes look at how I used GitHub Copilot as an AI pair programmer to build this Astro-powered personal blog and deploy it for free with GitHub Pages.

Building a personal blog from scratch can feel daunting — choosing the right framework, wiring up components, writing deployment pipelines, and keeping the whole thing maintainable. In this post I want to share exactly how I used GitHub Copilot as an AI pair programmer to accelerate every stage of building this site, and how GitHub Pages makes hosting it completely free and effortless.

Why GitHub Copilot?

I already spend most of my day inside VS Code working with infrastructure-as-code, Kubernetes manifests, and CI/CD pipelines. GitHub Copilot integrates directly into that workflow without switching context. Instead of jumping to documentation or Stack Overflow, I can describe what I need in a comment or a chat message and get working code back in seconds.

For a side project like a personal blog, that speed-up is the difference between shipping something and leaving it as a forever-draft.

Choosing the Stack

I wanted a static site — fast, secure, and cheap to host. After a quick research session (with Copilot Chat summarising the trade-offs), I settled on:

ToolRole
AstroStatic site generator with component islands
Tailwind CSSUtility-first styling
MarkdownContent authoring
GitHub PagesHosting & CDN
GitHub ActionsBuild & deploy pipeline

Copilot Chat helped me compare Astro, Next.js, and Hugo side-by-side without leaving my editor, and suggested Astro because of its zero-JS-by-default philosophy — perfect for a content-heavy blog.

Scaffolding the Project

I started with npm create astro@latest to scaffold the project, then immediately opened Copilot Chat and asked:

“I have a fresh Astro project. I want a blog with a homepage, a blog listing page, and individual post pages. What folder structure should I use and can you generate the base layouts?”

Within a few exchanges I had:

  • src/layouts/BaseLayout.astro — shared <head>, header, and footer
  • src/layouts/BlogPost.astro — layout for individual posts with metadata
  • src/components/Header.astro and src/components/Footer.astro
  • src/pages/index.astro — homepage
  • src/pages/blog/index.astro — post listing
  • src/pages/blog/[...slug].astro — dynamic post route

What would have taken me the better part of an afternoon took about 30 minutes, with most of that time spent reviewing and tweaking the generated output rather than writing from scratch.

Building Components with Copilot

BlogCard Component

I needed a card to display post previews. I typed:

// BlogCard component: receives title, description, pubDate, heroImage, slug props
// Renders a card with the hero image, date, title, description, and a "Read more" link

Copilot completed the full component, including responsive image handling and accessible link text. I asked a follow-up in chat to add tag badges, and it updated the component inline.

I asked Copilot Chat:

“In Astro, how do I highlight the active nav link using Astro.url?”

It gave me the exact pattern — comparing Astro.url.pathname to each href — and autocompleted the implementation as I typed it.

Dark Mode Toggle

Tailwind’s dark: variant makes dark mode straightforward, but wiring up the toggle with localStorage persistence always involves a bit of boilerplate. A single prompt got me a working script that:

  1. Reads the saved preference from localStorage on page load
  2. Falls back to the OS preference via prefers-color-scheme
  3. Toggles the dark class on <html> and saves the new preference

Writing Content

Every blog post is a Markdown file in src/content/blog/. The Astro content collections API validates frontmatter automatically. When I defined the schema in src/content.config.ts, Copilot autocompleted the Zod schema based on the frontmatter fields I had already written in my first post.

For the posts themselves, Copilot is useful for:

  • Generating outlines — I describe the topic and ask for a heading structure
  • Expanding sections — I write a rough bullet list and ask Copilot to turn it into paragraphs
  • Code snippets — CLI commands and config examples are autocompleted accurately
  • Proofreading — Copilot Chat can suggest clearer phrasing

I still write the narrative voice myself; Copilot handles the scaffolding so I can focus on the ideas.

Setting Up GitHub Pages

GitHub Pages can serve any static site from a repository. For an Astro project the recommended approach is to let a GitHub Actions workflow build the site and push the output to the gh-pages branch (or use the new Pages artifact upload action).

The Workflow File

Copilot Chat wrote the first draft of .github/workflows/deploy.yml when I asked:

“Write a GitHub Actions workflow that builds an Astro site and deploys it to GitHub Pages using the official GitHub Pages action.”

The result used withastro/action — the official Astro action that handles Node setup, dependency installation, building, and artifact upload in a single step — plus actions/deploy-pages for the actual deployment. Here is the workflow used by this blog (see deploy.yml):

name: Deploy to GitHub Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install, build, and upload your site
        uses: withastro/action@v3
        with:
          node-version: 22

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

A few things worth noting:

  • withastro/action handles the full build pipeline (install → build → upload artifact) in one step, so there is no need to manually call npm ci, npm run build, or upload-pages-artifact separately.
  • workflow_dispatch lets you trigger a manual deployment from the GitHub Actions UI without pushing a commit.
  • concurrency ensures only one deployment runs at a time and that in-progress deployments are never cancelled mid-flight.

Enabling Pages in the Repository

  1. Go to Settings → Pages in your repository.
  2. Under Build and deployment, choose GitHub Actions as the source.
  3. Push a commit to main — the workflow runs automatically and your site is live at https://<username>.github.io/<repo>.

A custom domain is just as easy: add a CNAME file to the public/ directory in Astro (so it ends up in dist/) and point your DNS to GitHub’s servers.

The Development Loop

My typical workflow for a new post or feature:

  1. Branchgit checkout -b feature/my-new-post
  2. Write — draft content or code with Copilot inline suggestions
  3. Review — Copilot Chat reviews the diff and flags anything odd
  4. Commit & pushgit push origin feature/my-new-post
  5. Pull request — GitHub Actions runs a build check on the PR
  6. Merge to main — the deploy workflow fires and the site updates in under two minutes

Lessons Learned

Copilot is Best as a First Draft Machine

Copilot is fastest when I treat its output as a starting point, not a finished product. I always review generated code for correctness, style consistency, and accessibility before committing.

Chat vs. Inline Completions

  • Inline completions shine for repetitive patterns: frontmatter, component props, Tailwind class strings.
  • Copilot Chat is better for architectural questions, debugging, and multi-file changes.

Trust but Verify

Copilot occasionally generates outdated API usage (e.g., deprecated Astro APIs). Cross-referencing with the official Astro docs takes seconds and is always worth it.

GitHub Pages: The Hosting Story

GitHub Pages has been rock-solid for this site. Key benefits:

  • Free for public repositories
  • Automatic HTTPS via Let’s Encrypt
  • Global CDN backed by Fastly
  • Zero maintenance — no servers, no containers, no bills

For a personal blog with static content, there is genuinely no reason to reach for anything more complex.

Wrapping Up

GitHub Copilot cut the time I spent on boilerplate in half and kept me in flow while building this site. Paired with GitHub Pages, the result is a fast, free, and fully automated publishing pipeline — from writing a Markdown file to a live post in two minutes.

If you are thinking about starting your own blog, this stack is hard to beat. The barrier to entry is low, the tooling is excellent, and having an AI pair programmer in your corner makes the whole process genuinely enjoyable.

Have questions about the setup? Feel free to reach out or open a discussion in the repository.

Back to all posts