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

  1. Create a new repo on GitHub: blog_webdesigndaddy
  2. Push all these files to it
  3. Go to Netlify → New site from Git → Connect your repo
  4. In Netlify site settings → Environment variables → Add the three PUBLIC_CMS_* variables
  5. 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