A lightning-fast, SEO-optimized blog built with Astro and deployed on Cloudflare Pages. Features modern web development practices, excellent performance scores, and a seamless content management workflow.
- Lightning Fast: Built with Astro for optimal performance
- SEO Optimized: Complete meta tags, structured data, and sitemap generation
- Modern Design: Responsive, accessible, and beautiful UI with dark/light mode
- Centralized Color System: Easy theme customization with CSS custom properties
- Email Capture: Built-in CRM integration for subscriber management
- Developer Experience: TypeScript, Tailwind CSS, and hot reloading
- Content Management: Markdown-based posts with frontmatter
- Search & Filter: Client-side search and tag filtering
- RSS Feed: Automatic RSS feed generation
- Performance: Lighthouse scores 90+ across all metrics
- Deployment: Automated CI/CD with GitHub Actions to Cloudflare Pages
- Lighthouse Performance: 90+
- First Contentful Paint: <1.5s
- Largest Contentful Paint: <2.5s
- Cumulative Layout Shift: <0.1
- Time to Interactive: <3s
- Framework: Astro
- Styling: Tailwind CSS
- Deployment: Cloudflare Pages
- CI/CD: GitHub Actions
- Performance: Lighthouse CI
- Content: Markdown with frontmatter
- Node.js 18+
- npm or yarn
- Git
- GitHub account
-
Clone the repository
git clone https://github.com/seefor/cf_blog.git cd cf_blog -
Install dependencies
npm install
-
Set up GitHub Discussions for comments
- Go to your repository Settings β Features
- Enable "Discussions" β
- Install Giscus app: https://github.com/apps/giscus
- Configure at https://giscus.app and update
src/components/Comments.astro
-
Start development server
npm run dev
-
Open your browser Navigate to
http://localhost:4321
npm run build
npm run preview-
Create a new Markdown file in
src/content/blog/touch src/content/blog/my-new-post.md
-
Add frontmatter and content
--- title: 'Your Post Title' description: 'A brief description of your post' pubDate: 2024-01-15 author: 'Your Name' tags: ['tag1', 'tag2', 'tag3'] featured: false draft: false image: '/blog/post-image.jpg' --- Your post content goes here...
-
Commit and push
git add . git commit -m "Add new blog post: Your Post Title" git push
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | β | Post title |
description |
string | β | Meta description |
pubDate |
date | β | Publication date |
author |
string | β | Author name |
tags |
array | β | Post tags |
featured |
boolean | β | Featured post flag |
draft |
boolean | β | Draft status |
image |
string | β | Social share image |
updatedDate |
date | β | Last updated date |
- Push to GitHub: Commit and push your code to GitHub
- Connect to Cloudflare Pages:
- Go to Cloudflare Pages
- Click "Create a project" β "Connect to Git"
- Select your repository
- Configure build settings:
- Framework preset:
Astro - Build command:
npm run build - Build output directory:
dist - Root directory:
/(leave empty)
- Framework preset:
- Deploy: Click "Save and Deploy"
-
Get Cloudflare credentials:
- API Token: Cloudflare Dashboard β My Profile β API Tokens β Create Token
- Account ID: Cloudflare Dashboard β Right sidebar
-
Add GitHub repository secrets:
CLOUDFLARE_API_TOKEN: Your API tokenCLOUDFLARE_ACCOUNT_ID: Your account IDLHCI_GITHUB_APP_TOKEN: Lighthouse CI token (optional)
-
Update workflow: Edit
.github/workflows/deploy.ymland changeprojectName: your-blogto your actual project name -
Push to main branch to trigger deployment
Add these in Cloudflare Pages β Settings β Environment variables:
NODE_VERSION=18
ASTRO_TELEMETRY_DISABLED=1
- Add domain: Cloudflare Pages β Custom domains β Set up a custom domain
- Update site URL: Edit
astro.config.mjs:export default defineConfig({ site: 'https://yourdomain.com', // ... other config });
- Update DNS: Follow Cloudflare's DNS instructions
Comments are powered by GitHub Discussions and are required for full functionality:
- Enable GitHub Discussions: Repository Settings β Features β Discussions β
- Install Giscus: Visit https://github.com/apps/giscus and install for your repository
- Configure: Go to https://giscus.app and get your configuration values
- Update: Edit
src/components/Comments.astrowith your actual values:const REPO = "your-username/your-repo"; const REPO_ID = "your-repo-id"; const CATEGORY = "General"; const CATEGORY_ID = "your-category-id";
The blog includes an email capture component on the About page for building your subscriber list:
- Works automatically when deployed to Netlify
- View submissions in Netlify Dashboard β Forms
- No additional configuration needed
- Choose your service: Edit
src/config/crm.jsand set your preferred service - Add environment variables in Cloudflare Pages β Settings β Environment variables:
# For Mailchimp MAILCHIMP_API_KEY=your-api-key MAILCHIMP_SERVER_PREFIX=us1 MAILCHIMP_LIST_ID=your-list-id # For ConvertKit CONVERTKIT_API_KEY=your-api-key CONVERTKIT_FORM_ID=your-form-id - Update API endpoint: Modify
src/pages/api/subscribe.jsto use your chosen service
- Netlify Forms (default, no setup required)
- Mailchimp - Popular email marketing platform
- ConvertKit - Creator-focused email marketing
- Klaviyo - E-commerce email marketing
- Brevo (formerly Sendinblue) - All-in-one marketing platform
-
Update site information in:
src/layouts/Layout.astrosrc/components/Header.astrosrc/components/Footer.astroastro.config.mjs
-
Replace favicon in
public/favicon.svg -
Customize colors: The blog uses a centralized color system for easy theming:
- Quick changes: Edit
src/config/theme.jsto modify all colors at once - Advanced: Edit
src/styles/colors.cssfor fine-grained control - Semantic classes: Use
bg-primary,text-secondary,border-DEFAULTinstead of hardcoded Tailwind colors - Colors automatically adapt for light/dark modes
- Quick changes: Edit
- Create a new
.astrofile insrc/pages/ - Use the Layout component:
--- import Layout from '../layouts/Layout.astro'; import Header from '../components/Header.astro'; import Footer from '../components/Footer.astro'; --- <Layout title="Page Title" description="Page description"> <Header /> <main> <!-- Your content --> </main> <Footer /> </Layout>
- β Meta tags (title, description, Open Graph, Twitter Cards)
- β Structured data (JSON-LD schema markup)
- β Canonical URLs
- β XML sitemap generation
- β RSS feed
- β Robots.txt
- β Performance optimization
- β Mobile responsiveness
- β Accessibility compliance
- Optimize images: Use WebP format and include alt text
- Write good meta descriptions: Keep under 160 characters
- Use proper heading hierarchy: H1 β H2 β H3
- Internal linking: Link to related posts
- External links: Use
rel="noopener noreferrer"
cf_blog/
βββ src/
β βββ components/ # Reusable components
β βββ content/
β β βββ blog/ # Blog posts (Markdown)
β βββ layouts/ # Page layouts
β βββ pages/ # Routes and pages
βββ public/ # Static assets
βββ .github/
β βββ workflows/ # GitHub Actions
βββ package.json
npm run dev # Start development server
npm run build # Build for production
npm run preview # Preview production build
npm run astro # Run Astro CLI commands# Add a new dependency
npm install package-name
# Add a dev dependency
npm install -D package-name- Build fails: Check Node.js version (requires 18+)
- Images not loading: Ensure images are in
public/directory - Styles not applying: Check Tailwind CSS configuration
- 404 on deployment: Verify build output directory is
dist
- Run Lighthouse audit:
npm run build && npm run preview - Check bundle size: Use browser dev tools
- Optimize images: Use modern formats (WebP, AVIF)
- Review Core Web Vitals: Monitor real user metrics
- Astro Documentation
- Tailwind CSS Documentation
- Cloudflare Pages Documentation
- Web.dev Performance Guide
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Astro
- Styled with Tailwind CSS
- Deployed on Cloudflare Pages
- Icons from Heroicons
Ready to start blogging? π
- Customize the branding and content
- Add your first blog post
- Deploy to Cloudflare Pages
- Share your amazing content with the world!
For questions or support, please open an issue or contact us.