Lesson 3.1 is new: "Send Merge Campaigns at Scale, Safely". It covers bulk merge personalization and a full safe-send protocol. The old Lesson 3.1 is now 3.2 at the same URL. The course now has 4 modules and 20 lessons. New blog posts: a case study of a real merge send, GitHub pull requests for marketers, "I Turned a Markdown File into a Real Book in 4 Minutes", and "Offline Notes: Keep the Reason You Saved It". Blog posts can now show real tables. The library has a new B2B Enterprise Naming entry, linked from three related entries. The footer now lists all cc4 tools in four columns: brand, Learn, Free tools, and Support. Every blog post now ends with a donation section: PayPal, Ko-fi, and a VietQR card for Vietnamese readers that opens the QR code in a pop-up. Missing blog, library, and author pages now show a real 404. Links to /modules/N/ now go to the right place on the modules page. The download form now sends your email to a new sign-up route. The success message includes Substack's own subscribe box, with a plain link as a backup.
39271d2 feat(download): let readers subscribe through the Substack embed; 4322481 fix(signup): drop the server-side Substack subscribe; 6ed3fb9 feat(changelog): compute weekly entry range, filter, bump and modules in node; 38d1cec feat(download): add the site-kick honeypot field and restore the Substack line; b7cbd36 feat(course-download): subscribe to Substack after live delivery, run list signups in waitUntil; 67fee40 feat(download): post the form to /api/course-download with an idempotency key; 8cff177 feat(course-download): add reader to Resend audience after live delivery, carry subscribe mail copy; 523b054 feat(wrangler): MAIL_MODE=live and MAIL_FROM for site-kick mail on cc4.marketing; f558f03 feat(wrangler): bind cc4-mkt to site-kick-gateway, bump site-kick to v0.2.2; adf2026 feat(api): serve the course download through the site-kick book handler; 5e57395 feat(wrangler): add cc4-mkt-preview env bound to site-kick-gateway-preview; 36e87a0 feat(llms): cache llms.txt for one hour; a8f364b feat(llms): generate llms.txt from posts, lessons and library entries; f88c854 feat(seo): blog posts honour EmDash SEO panel title, description and noindex; ddd06fa fix(seo): real 404s for missing blog/library/author pages, fit long titles and descriptions; 867ec7a fix(security): harden CMS and clarify AI authorship; d0292e7 fix(security): rate-limit and lock down /api/subscribe, drop /api/feedback, escape changelog + JSON-LD, add HSTS/CSP; 709dc2c fix(seo): stop /modules/N/ soft-404 chain, add lesson schema, tighten meta, fix robots groups; b97c9e9 feat(seo): list all cc4 tools in llms.txt and footer, add Offline Notes; c0fc537 feat(blog): publish GitHub pull requests for marketers post; 45d2e83 feat(analytics): first-party ledger beacon on s.cc4.marketing; c85b9e3 feat: publish "Offline Notes: Keep the Reason You Saved It" blog post; 717af02 feat(scripts): resend env setup CLI, dev.vars fallback for sync check, phase 02-04 report; 91be53e fix(subscribe): server-side Substack sync, real validation, reconcile guard; 4b13468 feat(blog): add real table block type, use it for the naming scoring matrix; 1679da5 feat(blog): draft naming-framework post + cover/inline illustrations; 9007979 feat: sitemap footer with sister-product cross-links and donate chip; 2e338e9 feat: donation block under blog posts + newsletter footer donate link; c110e33 feat: donation section 3-col row with VietQR modal and conversion copy; 41ddfba feat: add VietQR donation card for Vietnamese users; 6c2b503 feat: publish "I Turned a Markdown File into a Real Book in 4 Minutes" blog post; de8e3d7 feat(library): reciprocal related links to b2b-enterprise-naming; 2adcdb2 feat(library): add B2B Enterprise Naming entry page; 3c7dd77 feat(sitemap): auto-generate blog lastmod from D1 at build; b8998f7 fix(seo): noindex /_emdash/* via _headers (asset layer); a55fba2 fix(seo): force https + noindex Emdash admin routes; 3e80927 feat(analytics): add self-hosted Plausible alongside Beam and GA4; d122e97 fix: add Module 3.1 to OG smoke-test expected list; d102f12 feat: Module 3.1 (merge campaigns) + case-study blog post + hello bar/banner update
New 60-minute lesson covering bulk, structured merge-personalization and the full safe-send protocol — preview, test, dry-run, explicit confirm, record. Paired with an open starter kit (campaign-merge-kit) and a companion blog post walking through a real send: the Gmail clipping bug, an encoding bug, a wrong tracking claim caught on verification, and why a 100% open rate from a list of banks isn't the win it looks like. The former Lesson 3.1 (sigil capstone) is now 3.2. Course now: 4 modules, 20 lessons.
Added /modules/3/merge-campaigns-safely/ (order 19, was previously occupied by sigil capstone, now moved to /modules/3/ship-with-sigil/ order 20). Added blog post /blog/what-i-caught-before-a-coding-agent-sent-real-emails/ with FAQPage schema, byline tri-vo, cross-links to both Module 3 lessons and the Resend setup checklist post. Added public GitHub repo blacklogos/campaign-merge-kit. Updated astro.config.mjs blogPages, llms.txt, llms-full.txt, faq.astro and index.astro lesson counts (18→20), hello bar and floating banner CTAs.
Blog design system: solid ink/tint token palette derived from the brand colors, with a contrast check script (npm run check:blog-tokens) verifying WCAG pairs in both themes.
Solid pre-computed ink/tint/shadow/sheet CSS tokens in global.css replace ad-hoc rgba mixes; WCAG contrast pairs verified by scripts/check-blog-tokens.mjs in light and dark.
Blog post reading view redesigned as a document-on-desk sheet: spec-plate masthead with breadcrumb, author and read-time chips; framed code blocks; floating table of contents on desktop, native disclosure on mobile.
[slug].astro decomposed into PostMasthead/PostToc/PostNav/PostCta components on a bordered --sheet surface; sticky desktop TOC, details-based mobile TOC.
New blog post by Alice Marketer: Set Up Resend Right: A Marketer's Checklist with an AI Agent — eight-item Resend setup checklist with a copyable agent audit prompt.
New published post resend-setup-checklist-for-marketers with bespoke cover.
Mobile performance: fonts are self-hosted with preload instead of chained through fonts.googleapis.com, removing ~850ms of render-blocking. The quickstart video iframe lazy-loads.
Outfit variable + Righteous woff2 self-hosted; Google Fonts CSS chain removed; video iframe lazy.
Secondary text and shadows now derive from the brand ink as solid colors (no translucency); blog links carry persistent underlines; dark mode swaps once at token level.
--text-secondary aliases --ink-70; --shadow-* opaque; persistent 2px underlines on blog prose links.
Blog index and author pages swap raw color literals for the shared tokens (no layout changes).
Mechanical rgba-to-token substitution in index.astro, authors.astro, authors/[slug].astro, BlogContent release box.
Reverted page prerendering: with Emdash middleware on Cloudflare Workers, prerendered routes fail the setup DB check and every page redirected to /_emdash/admin/setup. All pages are SSR again.
Prerender flags removed; smoke test must check url_effective.
robots.txt no longer contains the invalid LLMs-txt directive or the non-standard Crawl-delay/Host lines that Search Console flagged.
robots.txt cleaned to standard directives.
Sitemap URLs use canonical trailing-slash form and no longer stamp fake lastmod on every deploy; non-slash URLs 301 to canonical.
Sitemap lastmod omitted; trailing-slash 301s; Threadmark URL canonicalized.
Broken blog TOC drawer script removed (it threw a TypeError on load); the table of contents is now JS-free.
initTOC NodeList.filter TypeError eliminated; native details on mobile, sticky nav on desktop.
The Module 2.7 launch post got a full SEO/AEO pass: tighter title and excerpt, question-form headings, skimmable lists, and internal links. Also fixed: the post was missing from the sitemap, llms.txt, and llms-full.txt.
Rewrote /blog/service-package-from-real-engagement content in D1 (title 56 chars, excerpt 144, question-form H2s, 10 list items, 4 internal links). Added slug to astro.config.mjs blogPages, llms.txt, llms-full.txt.
New 60-minute lesson: turn a completed client engagement into a sellable service package with the mine → decide → blueprint → derive practice. Includes copy-paste prompts, quality gates, and an Alice Marketer blog post with the full packaging prompt. Course now: 4 modules, 19 lessons.
Added /modules/2/service-package-from-engagement/ (order 18, capstone bumped to 19) and /start-2-7 course command; module 2 now 7 lessons. Blog post service-package-from-real-engagement (byline Alice Marketer) with full copyable prompt; new cover asset; HelloBar repointed to the lesson.
New 75-minute hands-on capstone lesson that bridges Modules 0-2 into a real, shippable artifact: a personalized post-event follow-up campaign powered by sigil, an open-source MIT CLI inside Claude Code. Course now: 4 modules, 18 lessons.
Added /modules/3/ship-with-sigil/ — capstone lesson using blacklogos/sigil CLI for a real email send pipeline on Cloudflare Workers, custom /email-rewrite slash command, per-recipient handcrafted sentences. Home and llms.txt updated to 4 modules / 18 lessons.
Sticky desktop sidebar inside every lesson shows all modules and lessons with current highlighted and a progress bar; mobile collapses to an off-canvas drawer. New /modules/ hub lists every module and lesson (previously 404).
Added LessonSidebar.astro (sticky on desktop, off-canvas drawer on mobile via FAB) integrated into LessonLayout via CSS grid. New /modules/ hub at src/pages/modules/index.astro reads from the content collection. Companion OG page key "modules" added.
Site now runs both Google Analytics 4 (gtag.js) and Beam Analytics for cross-checked traffic data. GA4 tag is inlined in <head>; no changes to existing Beam tracking.
Added GA4 gtag.js snippet inline in BaseLayout.astro <head>, next to existing Beam tag. No env gating — fires on all environments. Beam unchanged.
The top hello bar and the floating lesson promo banner now drive traffic to the new Module 3 capstone. Storage keys bumped so previously-dismissed visitors see the fresh content.
Updated promo.ts helloBar and lessonBanner targets to /modules/3/ship-with-sigil/. LessonPromoBanner.astro copy refreshed (NEW CAPSTONE badge, sigil highlights, internal CTA). Storage keys: hellobar-m3-sigil-capstone and lesson-promo-m3-sigil-capstone.
Clicking the author name on a blog post now goes directly to the personal author page (/blog/authors/{slug}/) instead of the hub-with-anchor. JSON-LD Person.author.url updated to match for SEO canonicalization.
src/pages/blog/[slug].astro authorUrl changed from /blog/authors/#{slug} to /blog/authors/{slug}/. JSON-LD BlogPosting.author.url updated automatically via the same variable.
Fixed table of contents anchor links not scrolling to target sections. H2 headings rendered by PortableText now have proper id attributes for anchor navigation. Moved ID generation from page template into content renderer.
cc4-marketing/site. src/components/BlogContent.astro: moved H2 detection from [slug].astro into renderer, wrap h2 blocks in <div id={headingId}> to provide anchor targets. Added headingId property to Segment type, slugify() function generates deterministic IDs (lowercase, alphanumeric+hyphens). Fixed smooth scroll navigation and IntersectionObserver active highlighting.
Added Release Highlight Box for product releases with version, download, landing page, and source links. Added auto-generated Sticky Table of Contents from H2 headings with smooth scroll navigation and active section highlighting. Desktop: right sidebar with sticky positioning. Mobile: collapsible drawer.
cc4-marketing/site. src/components/BlogContent.astro: new releaseHighlight block handler, minimal style (left border, tinted bg). src/pages/blog/[slug].astro: H2 extraction from content, TOC generation at build time, desktop sticky sidebar (.blog-toc-sticky, position: sticky top 100px), mobile drawer (.blog-toc-drawer, fixed left -100% sliding to 0), IntersectionObserver for active highlighting, smooth scroll JS. Threadmark post: 7 H2 sections + v0.4.0 release box.
Added FAQPage schema to the Claude Code marketing guide and HowTo schema (5 steps) to the campaign brief post, enabling Google rich results for both. Expanded all 17 lesson meta descriptions from 63-101 to 148-160 chars. Rephrased 8 H2 headings as questions across 4 key lessons for featured snippet targeting.
cc4-marketing/site. blog/[slug].astro: slug-keyed extraSchemas map; FAQPage on claude-code-for-marketing-guide-2026 (4 Q&A pairs), HowTo on write-campaign-brief-with-ai (5 steps, totalTime PT10M). All 17 src/content/modules/**/*.mdx description fields expanded to 148-160 chars. Question-form H2 rephrases in 0.0-introduction (2), 1.4-agents (2), 2.1-campaign-brief (2), 2.6-seo-optimization (2).
Fixed Course schema duplication (now only on homepage), corrected publisher logo dimensions to 180x180, added standalone BreadcrumbList schemas to blog index and lesson pages, fixed blog title tags to stay under 60 chars, expanded homepage and blog descriptions, and updated llms.txt with all 6 blog post URLs.
cc4-marketing/site. BaseLayout: showCourseSchema default false, titleSuffix split (articles get '| CC4M'), publisher logo og-image.png→apple-touch-icon.png (180x180). LessonLayout: 3-level BreadcrumbList (Home→Module N→Lesson), module-enriched title prefix. blog/index.astro: standalone top-level BreadcrumbList script tag. blog/[slug].astro: per-post keywords from title stopword filter, author URL with #anchor for named authors, publisher logo fix. robots.txt: added Google-Extended, Meta-ExternalAgent, Bytespider, cohere-ai. llms.txt + llms-full.txt: all 6 posts listed. sitemap: lastmod added. Homepage description trimmed to 159 chars.
Published three new posts: 'castmd: Vibe Coding a Chrome Extension for LLMs' by Tri Vo on rebuilding a Chrome extension with Claude Code; 'The Last Mile of Shipping Is the Hardest Part' by Tri Vo on turning manual release steps into slash commands; and 'AI Works Best When It Looks at What You've Already Shipped' by Alice on extracting real workflows from shipped work.
cc4-marketing/site. Three posts published to Emdash D1. Slugs: castmd-vibe-coding-chrome-extension (Tri Vo, 2026-04-28), the-last-mile-of-shipping (Tri Vo, 2026-04-20), ai-workflows-not-automation (Alice Marketer, 2026-04-15). All with bespoke 1200x630 cover images, bylines, featured_image set in D1, and entries in llms.txt/llms-full.txt.
Auto-generated social share cards for every page using a typographic engine (Satori + resvg-wasm on Cloudflare Workers). Blog posts get runtime-rendered cards with author avatar and excerpt; all other pages get build-time cards. Content-hashed URLs enable automatic cache invalidation.
cc4-marketing/site. workers-og Cloudflare Worker using Satori + resvg-wasm. Build-time static OG cards for homepage, blog index, changelog, authors, download, brand-guide, and all 17 module lessons (at /og/pages/{key}.png). Runtime-rendered blog post cards at /og/blog/{slug}-{hash}.png with author circular avatar, post title, and excerpt. R2 cache + content-hashed URLs for automatic invalidation. Dev-only /og-preview UI and /og/debug endpoint. PNG tEXt metadata embeds engine version and generation timestamp.
Launched /blog powered by Emdash CMS on Cloudflare D1. Upgraded from Astro 5 to Astro 6 with @astrojs/cloudflare adapter. Blog features SEO-optimized posts, author pages, structured data, custom OG images, and Substack newsletter CTA. Two launch posts published.
cc4-marketing/site v0.3.0. Astro 5→6 upgrade with @astrojs/cloudflare adapter (server mode). Emdash CMS integration with D1 database and R2 storage. New /blog section with SSR post index and detail pages (PortableText rendering). /blog/authors static page with Person schema. BlogPosting + CollectionPage + AboutPage structured data. Custom og-blog.png OG image. Blog cover illustrations per post. Migrated /api/subscribe from custom worker.js to Astro API route using cloudflare:workers env. Added live.config.ts for Astro Live Collections. Nav updated with Blog link. Sitemap priority 0.9 for blog routes. llms.txt updated with blog section.
Full changelog system: timeline page with version grouping and search, homepage What's New section, lesson update banners, /whats-new Claude Code skill, llms.txt for AI agents, and auto-changelog CI.
cc4-marketing/site. BearlyChange on Cloudflare Workers + KV. /changelog page with timeline, filter pills, search. WhatsNew homepage section. ModuleUpdatesBanner on lesson pages. /whats-new skill. llms.txt and llms-full.txt. Auto-changelog GitHub Actions workflow. RSS and JSON Feed. Keep a Changelog convention with types: added, changed, fixed, deprecated, removed, security.
Fixed lesson counts to 17 across JSON-LD and homepage, corrected Module 0 to 4 lessons, normalized Ko-fi links, fixed SEO title duplication, and updated quickstart steps for Substack flow.
cc4-marketing/site. Corrected lesson count 16/18→17 in JSON-LD and homepage. Module 0 card 3→4 lessons. Normalized Ko-fi URLs. Fixed BaseLayout title template duplication. Updated install steps for Substack subscribe flow.
Moved site configuration to siteData.ts, added brand guidelines page and GitHub PR contribution guide, cleaned up unused components.
cc4-marketing/site. Created siteData.ts centralizing nav, modules, features, stats. Added brand-guide.astro and GitHub PR guide lesson. Removed unused email subscription API and navigation components.
Aligned course with current AI-powered marketing landscape. Updated all lesson content, tools, and examples to reflect 2026 best practices.
cc4-marketing/cc4.marketing v1.2.0. Major content refresh for March 2026. Fixed Planerio positioning/ICP drift across modules, resolved content consistency issues, standardized course-context.json as single source of truth, rewrote README for public release.
Added download page with Google Form email capture, comprehensive SEO meta tags, Open Graph, Twitter Cards, JSON-LD schemas, and social sharing assets.
cc4-marketing/cc4.marketing v1.1.0. Email capture at /download with Google Form integration. Full SEO: meta tags, OG, Twitter Cards, JSON-LD (WebSite, Course, BreadcrumbList). Favicon suite. Secret bonus content.
17 interactive lessons taught inside Claude Code with slash commands. Practice project as a strategist at Markit agency for Planerio (B2B SaaS).
cc4-marketing/cc4.marketing v1.0.0. 17 lessons via slash commands (/start-0-0 through /start-2-6). Markit agency practice project, CM and CF plugins, CLAUDE.md course context.
Course website with 17 lesson pages, dark mode, Substack subscription, donation support, SEO, and retro-futuristic design.
Initial release of cc4-marketing/site. Astro 5 static site with 3 modules (17 MDX lessons), dark mode, Substack email capture, PayPal/Ko-fi donations, GitHub feedback, JSON-LD SEO, GitHub Pages + Cloudflare deployment.
No updates yet. Check back soon!