WebDesignDaddy Blog Setup Guide
Create a simple, working Astro test site for blog.webdesigndaddy.com that pulls content from your WebDesignDaddy CMS
Overview
This guide walks you through building an independent Astro-powered blog that fetches content exclusively from your "WDD blog" site in the WebDesignDaddy CMS. The result is a fast, static site ready for deployment on Netlify.
1. Project Structure
Create a new folder named blog-webdesigndaddy with the following structure:
blog-webdesigndaddy/
├── src/
│ ├── pages/
│ │ ├── index.astro ← Homepage (blog list)
│ │ └── posts/
│ │ └── [slug].astro ← Individual post/page
│ ├── layouts/
│ │ └── Layout.astro
│ ├── components/
│ │ └── Header.astro
│ └── lib/
│ └── api.js ← Helper to fetch from CMS
├── public/
│ └── favicon.svg ← Optional
├── .env
├── astro.config.mjs
├── package.json
└── netlify.toml ← For Netlify deploy 2. Key Files (Copy-Paste Ready)
.env (Never commit this!)
PUBLIC_CMS_API_URL=https://my.webdesigndaddy.com/api
PUBLIC_CMS_API_KEY=wdd_U6Kt8ffr_yBzHLH5•••••••••••••••• ← your actual key from the CMS
PUBLIC_CMS_SITE_ID=1 ← change if your site has a different ID src/lib/api.js
const API_URL = import.meta.env.PUBLIC_CMS_API_URL;
const API_KEY = import.meta.env.PUBLIC_CMS_API_KEY;
const SITE_ID = import.meta.env.PUBLIC_CMS_SITE_ID;
export async function getSite() {
const res = await fetch(`${API_URL}/sites/${SITE_ID}`, {
headers: { Authorization: `Bearer ${API_KEY}` }
});
if (!res.ok) throw new Error('Failed to fetch site');
return res.json();
}
export async function getAllContent() {
const res = await fetch(`${API_URL}/sites/${SITE_ID}/content`, {
headers: { Authorization: `Bearer ${API_KEY}` }
});
if (!res.ok) throw new Error('Failed to fetch content');
return res.json();
}
export async function getContentBySlug(slug) {
const res = await fetch(`${API_URL}/sites/${SITE_ID}/content?slug=${slug}`, {
headers: { Authorization: `Bearer ${API_KEY}` }
});
if (!res.ok) return null;
const data = await res.json();
return data[0] || null;
} src/layouts/Layout.astro
---
import Header from '../components/Header.astro';
const { title = 'WDD Blog' } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<link rel="icon" href="/favicon.svg" />
<TrackingHead />
</head>
<body class="min-h-screen bg-gray-50">
<Header />
<main class="max-w-4xl mx-auto px-6 py-12">
<slot />
</main>
<footer class="text-center py-8 text-gray-600">
© 2025 WDD Blog — Powered by WebDesignDaddy + Astro
</footer>
<TrackingBody />
</body>
</html> src/components/Header.astro
---
import { getSite } from '../lib/api';
const site = await getSite();
---
<header class="bg-blue-900 text-white py-8 mb-12">
<div class="max-w-4xl mx-auto px-6 text-center">
<h1 class="text-4xl font-bold">{site.name}</h1>
<p class="mt-2 text-xl">{site.domain}</p>
</div>
</header> src/pages/index.astro (Blog Homepage)
---
import Layout from '../layouts/Layout.astro';
import { getAllContent } from '../lib/api';
const posts = await getAllContent();
const sortedPosts = posts.sort((a, b) => (b.created_at || '').localeCompare(a.created_at || ''));
---
<Layout title="Home">
<h2 class="text-3xl font-bold mb-8">All Posts</h2>
{sortedPosts.length === 0 ? (
<p>No content yet. Add some in the CMS!</p>
) : (
<ul class="space-y-8">
{sortedPosts.map(post => (
<li class="border-b pb-8">
<a href={`/posts/${post.slug}`} class="block">
<h3 class="text-2xl font-semibold text-blue-800 hover:underline">
{post.title || 'Untitled'}
</h3>
{post.excerpt && <p class="mt-2 text-gray-700">{post.excerpt}</p>}
<time class="text-sm text-gray-500">
{new Date(post.created_at).toLocaleDateString()}
</time>
</a>
</li>
))}
</ul>
)}
</Layout> src/pages/posts/[slug].astro (Individual Post)
---
import Layout from '../../layouts/Layout.astro';
import { getContentBySlug } from '../../lib/api';
export async function getStaticPaths() {
const posts = await getAllContent();
return posts.map(post => ({
params: { slug: post.slug }
}));
}
const { slug } = Astro.params;
const post = await getContentBySlug(slug);
if (!post) {
throw new Error(`Post not found: ${slug}`);
}
---
<Layout title={post.title || 'Post'}>
<article class="prose max-w-none">
<h1 class="text-4xl font-bold mb-4">{post.title}</h1>
<time class="text-gray-600">
{new Date(post.created_at).toLocaleDateString()}
</time>
<div class="mt-8" set:html={post.body_html} />
</article>
</Layout> astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
output: 'static',
site: 'https://blog.webdesigndaddy.com'
}); package.json (relevant parts)
{
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview"
},
"dependencies": {
"astro": "^4.15.0"
}
} 3. How to Deploy on Netlify
- Create a new repo on GitHub: blog_webdesigndaddy
- Push all these files to it
- Go to Netlify → New site from Git → Connect your repo
- In Netlify site settings → Environment variables → Add the three PUBLIC_CMS_* variables
- Deploy — your site will build and go live
4. Next: Add Content in CMS
Go to my.webdesigndaddy.com → Content → Add new posts/pages with Title, Slug, and Body (HTML is fine). Then trigger a Netlify rebuild or set up a webhook for auto-deploys.
That's it!
This gives you a fully independent, fast static blog powered by your CMS. Want adjustments (different design, Markdown support, images, etc.)? Just say the word. 🚀
Comments
Approved comments appear below. Log in once with GFAVIP — it applies across the whole site. GFAVIP login
View comments archive