← Back to blog

How to Create Web Portfolio + Blog Using Astro and Deploy to Cloudflare Pages

astrosetuptemplate

A single-file interactive setup script that turns the default Astro blog template into a fully styled portfolio and blog. Works on Windows, Mac, and Linux.

What You Get

  • Homepage with your name, tagline, tech stack, and latest blog posts
  • Blog with markdown posts, search, and pagination
  • Projects page with a card grid layout
  • Dark or Light theme with 8 accent color choices
  • Responsive layout with sticky nav and footer with social links
  • Zero dependencies — just Node.js (which you already have)

Requirements

  • Node.js v18 or higher
  • npm (comes with Node.js)
  • Git (for deployment)

Installation

1. Create a new Astro project

npm create astro@latest my-portfolio

When prompted:

  • How would you like to start? → Choose Use blog template
  • Install dependencies? → Yes
  • Initialize git? → Yes

2. Go into the project

cd my-portfolio

3. Download the setup script

Download setup.mjs and place it in the project root (same folder as package.json).

Your folder should look like:

my-portfolio/
├── src/
├── public/
├── package.json
├── astro.config.mjs
└── setup.mjs        ← here

4. Run the setup

node setup.mjs

The script will ask you:

PromptDescription
NameDisplayed in the hero, nav, footer, and favicon
TaglineShort bio shown on the homepage
LocationOptional — appended to your tagline
Tech stackComma-separated list shown as tags on homepage
Social linksGitHub, LinkedIn, Facebook, Twitter/X (all optional)
Color theme8 choices: Cyan, Emerald, Violet, Amber, Rose, Blue, Orange, Lime
Theme modeDark or Light
Footer creditWhether to show “Built with Astro” in the footer

After confirming, the script generates all files and you’re ready to go.

5. Start the dev server

npm run dev

Visit http://localhost:4321 to see your site.

Adding Blog Posts

Create a .md file in src/content/blog/:

---
title: "My New Post"
description: "A short summary of the post."
date: 2026-02-26
tags: ["web-dev", "tutorial"]
---

Write your content here using **Markdown**.

## Subheading

- Lists work
- Code blocks work
- Images work

That’s it. The post automatically appears on the blog listing and homepage.

Frontmatter Fields

FieldRequiredDescription
titleYesPost title
descriptionYesShort summary shown in post cards
dateYesPublication date (YYYY-MM-DD)
tagsNoArray of tags (default: [])
draftNoSet to true to hide the post (default: false)

Editing Projects

Open src/pages/projects.astro and edit the projects array:

const projects = [
  {
    title: "My Project",
    description: "What it does.",
    tags: ["Laravel", "MySQL"],
    link: "https://github.com/you/project",
  },
  // Add more...
];

Deployment (Cloudflare Pages)

1. Push to GitHub

git add .
git commit -m "initial commit"
git remote add origin https://github.com/yourusername/my-portfolio.git
git branch -M main
git push -u origin main

2. Connect to Cloudflare Pages

  1. Go to dash.cloudflare.com
  2. Navigate to Workers & PagesCreatePages tab
  3. Click Connect to Git and select your repo
  4. Set build settings:
SettingValue
Framework presetAstro
Build commandnpm run build
Build output directorydist
  1. Click Save and Deploy

Your site will be live at your-project.pages.dev within a minute.

Publishing new posts

# Write a new .md file in src/content/blog/
git add .
git commit -m "new post: my new post"
git push

Auto-deploys in about 30 seconds.

Customization

Changing colors after setup

Edit src/styles/global.css and update the CSS variables:

:root {
  --accent: #06b6d4;       /* Change this to any hex color */
  --accent-soft: rgba(6, 182, 212, 0.08);
  --accent-glow: rgba(6, 182, 212, 0.25);
}

Changing fonts

Replace the Google Fonts import in src/styles/global.css and update the --font-body and --font-mono variables.

Adding new pages

Create a new .astro file in src/pages/. For example, src/pages/contact.astro:

---
import Base from '../layouts/Base.astro';
---

<Base title="Contact">
  <section style="padding: 4rem 0;">
    <h1>Contact</h1>
    <p>Get in touch at [email protected]</p>
  </section>
</Base>

Then add it to the nav in src/layouts/Base.astro.

Re-running the setup

You can run node setup.mjs again at any time. It will overwrite the generated files with your new choices. Your custom blog posts in src/content/blog/ will not be deleted (only the sample hello-world.md gets recreated).

Troubleshooting

Build error: “Could not resolve…”

The blog template includes default files that the setup script removes. If you see this error, delete the file mentioned in the error:

# Example
rm src/pages/about.astro
rm src/pages/rss.xml.js

Then run npm run build again.

Search doesn’t filter posts

The search bar filters posts on the current page only. It uses client-side JavaScript — no server needed. If you have many posts across multiple pages, consider adding Pagefind for full-site search.

License

Free to use for personal and commercial projects. No attribution required.