---
title: "What Silently Dropped When dxdev-blog Folded Into dxdev-landing"
canonical: https://dxdev.com/blog/blog-merge-platform-decision/
datePublished: 2026-04-19
---
On April 19, two Cloudflare Pages deployments fired every time we published anything to dxdev.com. One for `dxdev-landing`, the marketing site. One for `dxdev-blog`, a completely separate Astro project sitting at the same domain. We had been running this arrangement for months and calling it architecture. It was an accident we had stopped noticing.

It meant double config, double deploy, and a standing question every time we wanted to add a page. Which repo owned this? Marketing? Blog? Something in between? The answer kept shifting, and neither repo accumulated the shared context it needed to answer cleanly. The blog's Astro content schema had grown to track series, episode, and reader tier. `dxdev-landing` knew none of it. The landing site's dev-host config, which let us preview the marketing site on a local network, had never been threaded through to the blog. Two surfaces serving a single product had stopped talking to each other.

Folding `dxdev-blog` into `dxdev-landing` was the obvious fix. We expected to spend an afternoon moving files. We spent the day doing product architecture.

## The merge exposed a schema nobody had written down

The blog's content model had grown in its own repo, loosely, responding to needs as they surfaced. Carrying it into `dxdev-landing` meant making it explicit.

The frontmatter for a post in the merged repo now carries eight fields that weren't previously shared: `series`, `episode`, `tier`, `tags`, `component`, `concern`, `phase`, and `status`. Each exists because a specific rendering question needed an answer that prose alone couldn't give. `tier` distinguishes free posts from paywalled content. `component` tracks which part of the product stack a post addresses. `concern` is narrower than `tags`, pointing at the operational problem rather than the general topic. `phase` marks where in a project arc the work happened.

None of these are decorative. A renderer that doesn't understand `tier` can't decide whether to show a paywall. A renderer that doesn't understand `series` can't build episode navigation. This is where content schema crosses from editorial metadata into rendering contract, and the merge was what made the crossing visible.

It also left us with a question: how many fields can pile up in frontmatter before the post renderer becomes a CMS by stealth? We don't have the threshold yet. What we have is the recognition that since `dxdev-landing` now owns both surfaces, this schema is shared infrastructure. Adding a field is no longer an editorial call. It ships with the next deploy.

## What the renderer forgot on the way over

Moving content is easier than moving capabilities.

`dxdev-blog` had a renderer feature we'd built for a post called "The 32-Day Revolution," written from multiple narrator viewpoints on the same arc of events. We'd added perspective-tab rendering for it, a mechanism for toggling between two framings of the same moment in the text. When we folded the blog into `dxdev-landing`, that capability dropped silently. The Astro component that handled it didn't transfer cleanly, and the merged site's renderer gave no indication anything was missing.

A content migration validates that text moved. It does not validate that rendering behavior moved with it. The perspective tabs on "The 32-Day Revolution" would have collapsed into a broken layout for any reader who hit that post on the new site. Nothing in the migration output flagged it. Catching it required knowing to look.

## Cleaning up while both surfaces were open

With both surfaces open at once, a handful of links on the public-facing pages turned out to point at GitHub repos that had been renamed or frozen since we'd written the posts that referenced them. It was not urgent. But with both surfaces mapped to the same mental model at the same time, fixing them then was cheaper than re-opening the context later.

Dead GitHub links are just wrong. Cleaning them at the merge point cost a few minutes and would have cost an afternoon of re-deriving context on a separate day.

## One deploy now carries both concerns

The practical change from this day is that `dxdev-blog` is frozen. Every future post, every renderer update, every schema change goes into `dxdev-landing`. Three posts moved from review to published on this day. The dev-host config got threaded through properly so we could preview the combined site on a local network. The GitHub Actions workflow dropped to a single run pushing to a single Cloudflare Pages project.

That sounds like a simplification, and it is. It also comes with coupling worth being direct about. When the blog and the marketing site share a deploy, a content edit and a homepage redesign go out in the same release window. A broken schema field in a draft post can hold back a marketing change. The two concerns are coupled now, and the coupling is real.

A few months ago we wrote about splitting a monorepo into several smaller repos because the coordination tax of keeping everything together was climbing faster than the simplicity gains. This is the inverse move. We collapsed two repos into one because they'd already converged on the same deploy target, the same Astro config, the same audience. The earlier split separated independent concerns. This merge recognized that `dxdev-landing` and `dxdev-blog` were never really independent, and the coupling they'd been hiding behind two repo names was always there.

## The schema was the work

Getting the text out of `dxdev-blog` and into `dxdev-landing` was the smallest part of the day. The perspective-tab renderer for "The 32-Day Revolution" needed reconstruction, since the Astro component hadn't transferred cleanly. The frontmatter schema had to be negotiated deliberately: which of the eight fields belonged in the shared contract, and which were `dxdev-blog` artifacts that could be dropped.

When a blog folds into a product site and both have to ship together, the frontmatter fields stop being editorial notes. The `tier` field in `dxdev-landing` determines whether a paywall component renders, and getting it wrong ships a content access bug to every visitor. Deciding what `tier` means when both surfaces share a single Cloudflare Pages deploy, and whether `concern` lives in the shared rendering contract or stays a local annotation, was the architecture. The file migration was mechanical. That part wasn't.

So when two sites merge, check that rendering behavior moved along with the text, because a migration can report success while a feature like the perspective tabs is gone. And expect content edits and marketing changes to go out in the same release window from then on.
