Zero to Published in 30 Minutes


Astro Blog: Zero to Published in 30 Minutes

A no-nonsense walkthrough that gets you from “I have nothing” to “my blog is live on the internet” using Astro and Cloudflare Pages. Designed for a front-end dev who has never touched a static site generator.


What you’ll have at the end

A live blog at a real URL (e.g., your-blog.pages.dev or your own domain), with one published post, hot-reload local development, and automatic deploys whenever you push to GitHub.


Prerequisites (verify these in 2 minutes)

Open Terminal and run these to check what you already have:

node --version    # need 18.20.8+ or 20.3.0+ (anything 22+ is fine)
npm --version     # any recent version
git --version     # any recent version

If Node is missing or too old, install the LTS from nodejs.org or use Homebrew: brew install node. Everything else you need (npm, npx) comes bundled with Node.

You’ll also need a GitHub account (you have one) and a free Cloudflare account (cloudflare.com, takes 60 seconds to create if you don’t have one).


Step 1: Create the Astro project (5 minutes)

In Terminal, navigate wherever you keep your projects, then:

npm create astro@latest

It’ll ask you a series of questions. Recommended answers for your first time:

QuestionAnswer
Where should we create your new project?./my-blog (or whatever name you want)
How would you like to start your new project?Use blog template ← important
Install dependencies?Yes
Do you plan to write TypeScript?No (keep it simple)
Initialize a new git repository?Yes

Wait about a minute while it installs. You’ll get a folder with a fully working blog, including styled pages, RSS feed, sample posts, and an “About” page.


Step 2: Run it locally (2 minutes)

cd my-blog
npm run dev

You’ll see something like:

🚀  astro  v4.x.x started in 234ms

   ┃ Local    http://localhost:4321/
   ┃ Network  use --host to expose

Open that URL in your browser. You’re looking at a working blog. Take 60 seconds to click around — there’s a homepage, a blog index, individual post pages, and an About page.

Leave this terminal running. The server hot-reloads when you change files, just like any modern front-end build tool.


Step 3: Look around the file structure (5 minutes)

In a new Terminal tab (or your editor), here’s the lay of the land:

my-blog/
├── src/
│   ├── content/
│   │   └── blog/              ← your posts go here as .md files
│   │       ├── first-post.md
│   │       ├── second-post.md
│   │       └── ...
│   ├── pages/                 ← URLs of your site
│   │   ├── index.astro        ← homepage
│   │   ├── about.astro
│   │   └── blog/              ← /blog routes
│   ├── layouts/               ← page templates
│   ├── components/            ← reusable HTML components
│   └── consts.ts              ← site title, description, etc.
├── public/                    ← static files served as-is (favicon, images)
├── astro.config.mjs           ← config (you probably won't touch this)
└── package.json

The two folders you’ll spend 95% of your time in: src/content/blog/ (writing posts) and src/pages/ (page templates and routing).


Step 4: Make it yours (8 minutes)

Change site title and description

Open src/consts.ts. It looks something like this:

export const SITE_TITLE = 'Astro Blog';
export const SITE_DESCRIPTION = 'Welcome to my website!';

Change those to your actual blog title and description. Save. Watch the browser auto-refresh.

Write your first real post

In src/content/blog/, create a new file called hello-world.md:

---
title: 'Hello World'
description: 'The first post on my new Astro blog'
pubDate: 'May 9 2026'
heroImage: '/blog-placeholder-1.jpg'
---

This is my first post on Astro. The Markdown just works.

## A subheading

Regular paragraph text. **Bold** and *italic* and [links](https://example.com) all work like you'd expect.

- Bullet points
- Also work
- Naturally

That's the whole format.

The block at the top between --- markers is called frontmatter — it’s just metadata Astro uses to build the post. Below it is plain Markdown.

Save the file. Refresh localhost:4321/blog — your post is there.

Delete the sample posts

When you’re ready, just delete the first-post.md, second-post.md, etc. files in src/content/blog/. Astro automatically updates.

(Optional) Tweak the styling

The CSS lives in src/styles/global.css. Edit anything you want. Hot-reload applies instantly.


Step 5: Push to GitHub (5 minutes)

Go to github.com/new and create a new repository:

  • Name: my-blog (or whatever)
  • Public or Private — your choice (Cloudflare Pages works with both)
  • Don’t initialize with README, .gitignore, or license — Astro already created those

GitHub will show you a “push an existing repository” snippet. The commands look like this (use the ones GitHub shows you with your actual username):

# In your my-blog folder, in Terminal:
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/YOUR-USERNAME/my-blog.git
git push -u origin main

Refresh GitHub — your code is up.


Step 6: Deploy to Cloudflare Pages (5 minutes)

  1. Log into dash.cloudflare.com.
  2. In the left sidebar, click Workers & Pages.
  3. Click CreatePages tab → Connect to Git.
  4. Authorize Cloudflare to access your GitHub (one-time setup).
  5. Select your my-blog repository.
  6. On the build settings screen:
    • Framework preset: Select Astro from the dropdown
    • Build command: npm run build (auto-filled)
    • Build output directory: dist (auto-filled)
    • Leave everything else default
  7. Click Save and Deploy.

Wait 1–2 minutes while Cloudflare builds your site. When it’s done, you’ll get a URL like my-blog-x7y.pages.dev. Click it.

Your blog is live on the internet.


What just happened (the mental model)

From this point on, your workflow is:

  1. Edit Markdown files locally
  2. git push
  3. Cloudflare automatically rebuilds and redeploys, usually in under 90 seconds

There’s no server. No database. No PHP. No plugins to update. Your site is just static HTML files served from Cloudflare’s CDN — which is why it’ll load in under 100ms anywhere in the world.


Hooking up a custom domain (5 minutes, optional)

In your Cloudflare Pages project: Custom domains tab → Set up a custom domain → enter your domain → follow the prompts. If your domain is already on Cloudflare, it’s literally one click. If it’s at another registrar, you’ll add a CNAME record they’ll tell you exactly how to format.


Common gotchas

“npm create astro@latest” fails with permission errors. You may need to clear npm’s cache: npm cache clean --force, then retry.

Hot reload doesn’t work. Make sure you’re editing files inside src/, not public/. Files in public/ are copied as-is at build time and don’t trigger reloads.

Cloudflare build fails with “Node version” error. Add an environment variable in your Cloudflare Pages project settings: NODE_VERSION = 20 (or 22).

You changed src/consts.ts but the browser title didn’t update. Some pages cache the title from a layout — try a hard refresh (Cmd+Shift+R).

Markdown post doesn’t appear in the blog index. Check your frontmatter — the pubDate field needs to be a real parseable date, and all required fields must be present. Look at the sample posts for the exact format.


What to learn next (in order of usefulness)

  1. Frontmatter fields: Open src/content.config.ts (or src/content/config.ts) to see exactly which fields are required for blog posts. You can add your own fields here (tags, author, draft flag, etc.).
  2. Components: Look at src/components/ and src/layouts/. Astro components (.astro files) are HTML with a script tag on top. Familiar territory for a front-end dev.
  3. Adding pages: Drop a new .astro or .md file in src/pages/ and it becomes a URL. That’s the entire routing system.
  4. RSS feed: Already configured at /rss.xml. Substack subscribers can plug your URL straight into their reader.
  5. Comments: Add Giscus (free, uses GitHub Discussions) when you want it. ~30 minutes.
  6. CMS for non-technical writers: If you ever want a UI-based editor for clients, look at Decap CMS or TinaCMS as a layer on top of this exact setup.

Total time check

StepEstimate
Prerequisites2 min
Create project5 min
Run locally2 min
Explore structure5 min
Customize8 min
Push to GitHub5 min
Deploy to Cloudflare5 min
Total32 min

Close enough. Welcome to the indie web.