How to Create Web Portfolio + Blog Using Astro and Deploy to Cloudflare Pages
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:
| Prompt | Description |
|---|---|
| Name | Displayed in the hero, nav, footer, and favicon |
| Tagline | Short bio shown on the homepage |
| Location | Optional — appended to your tagline |
| Tech stack | Comma-separated list shown as tags on homepage |
| Social links | GitHub, LinkedIn, Facebook, Twitter/X (all optional) |
| Color theme | 8 choices: Cyan, Emerald, Violet, Amber, Rose, Blue, Orange, Lime |
| Theme mode | Dark or Light |
| Footer credit | Whether 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
| Field | Required | Description |
|---|---|---|
title | Yes | Post title |
description | Yes | Short summary shown in post cards |
date | Yes | Publication date (YYYY-MM-DD) |
tags | No | Array of tags (default: []) |
draft | No | Set 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
- Go to dash.cloudflare.com
- Navigate to Workers & Pages → Create → Pages tab
- Click Connect to Git and select your repo
- Set build settings:
| Setting | Value |
|---|---|
| Framework preset | Astro |
| Build command | npm run build |
| Build output directory | dist |
- 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.