The most important migration commit did not add Cloudflare configuration. It moved the landing page and handbook into the same source tree and taught one command to build both.
That order is the main lesson from the Yangworks move. Hosting changed later. First, the repository had to answer a simpler question: which files make up yangworks.dev?
The history supports an account of source ownership, URL decisions, and deployment cleanup. It does not contain a before-and-after benchmark, a traffic graph, or a downtime record. This is not evidence that Workers made the site faster or cheaper. It is evidence that one repository became responsible for one public URL space.
Before: one site, several operational units
Commit 2d4e14f contained a root landing page and an architecture note. The note made a useful distinction: editorial content should live under the main domain, beginning with /handbook; product sites should remain separate, on their own subdomains or domains.
The deployed shape did not yet match that plan. The handbook source lived outside this repository. An older dev-money-handbook project was associated with blog.yangworks.dev, while the root site had its own direct-upload deployment. The landing page and the site’s substantial content were both static, but they did not share a build or release artifact.
Serving those files was not the hard part. Ownership was. The intended site map put the landing page at /, the handbook at /handbook/, and pages such as /about and /privacy alongside them. Keeping the handbook on another host preserved an old deployment boundary that no longer matched the public information architecture.
The URLs were the constraint
Chinese handbook pages already used short slugs such as why, niche, and growth. More descriptive slugs were tempting, but the source fragments contained hard-coded links such as ./niche.html. Renaming a generated file without rewriting and checking every cross-link would trade a theoretical keyword improvement for real broken navigation.
So the migration moved the handbook under /handbook and kept its leaf slugs. That decision is not glamorous, but it prevented the hosting move from becoming a content-wide URL rewrite.
The site also stayed static. The landing page was plain HTML and CSS; the handbook already used HTML fragments and a small Node builder. There was no need to introduce Astro, a CMS, or a client router simply because two static outputs needed to become one.
Product sites remained outside the repository. Consolidation applied to the personal site and editorial content, not to every property carrying the Yangworks name.
The build came before the host
Commit 56a256b did the structural work. It moved landing assets into src/site, brought the handbook into src/handbook, added src/pages for About and Privacy, and added static files such as robots.txt and the ads.txt placeholder. The landing page’s handbook link changed to /handbook/.
The root build.js then established the output contract. It recreated public/, copied the ordinary site directories into it, and invoked the handbook builder. package.json exposed the whole operation as npm run build.
At that point the repository had a platform-neutral answer to “what should production serve?” That made the eventual Cloudflare configuration small. It also created one place to inspect path ownership across the landing page, legal pages, static files, and handbook. Collision detection was not yet implemented, but there was finally one build in which it could be added.
Deleting public/ on every build is useful and unforgiving. Stale pages cannot linger after their sources disappear. On the other hand, a missing copy step or content file removes the output immediately; there is no previous artifact quietly filling the gap. That is the right behavior for a deterministic build, provided the generated tree and links are tested.
Workers configuration was the small commit
Commit 4095194 added wrangler.jsonc. The current static-assets portion is short:
{
"name": "yangworks",
"assets": {
"directory": "./public",
"not_found_handling": "404-page"
}
}
There is no Worker script. assets.directory points at the artifact the root build already knew how to make, and not_found_handling tells Workers to use the generated 404 page for misses.
That explicit setting is one practical difference between Pages and Workers Static Assets. Pages inferred SPA or custom-404 behavior from the output; Workers asks the project to choose with not_found_handling. For Yangworks, "404-page" is the relevant choice: there is no Worker code or SPA shell competing with the static routes.
Commit 6dc71e1 recorded the deployed arrangement: the GitHub repository connected to the main production branch, npm run build as the build command, and npx wrangler deploy as the deploy command. The same documentation recorded removal of the older handbook project and direct-upload root project.
Cloudflare recommends Workers for new projects and says Pages will remain supported, with new feature work focused on Workers. That made Workers a sensible destination while Yangworks was already changing its build and deployment. It does not make every stable Pages site an urgent migration.
The cutover was not captured in Git
The repository shows the end state, not the handoff. Cloudflare’s guide says to connect Workers Builds, disable Pages automatic deployments, validate the Worker, move production traffic, and only then delete the old project. Next time I would put those steps beside the custom-domain and route checks so two deployment systems cannot keep publishing by accident.
wrangler.jsonc also cannot prove which public endpoints remain enabled. Preview URLs and the default workers.dev address are Cloudflare account settings, so they need separate dashboard or HTTP checks.
Multilingual output expanded the artifact, not the deployment count
Commit 0971851 expanded the same artifact to three language trees without moving the original Chinese pages from /handbook/. The builder emits only translations backed by source files; the canonical and hreflang mechanics are covered in the multilingual static-site guide. The migration point is that languages expanded public/, not the number of deployments.
Commit bd2dcb7 supplied a more visible maintenance payoff: navigation and design-token changes across the landing page, legal pages, handbook, and 404 page shipped in one release while each page family kept its own layout.
The loose ends are more useful than a victory lap
- Internal links still take an extra hop. Some handbook links use relative
.htmlpaths while canonicals and sitemap entries use extensionless URLs. Workers currently redirects the file form, but the source and preferred public form are not yet fully aligned. - The language roots are HTML stubs.
/en/and/ja/use meta refresh, not HTTP 301 redirects. A browser reaching the intended page does not change the response semantics. - Git cannot describe the whole edge. The repository proves the build and Wrangler asset settings. It does not independently prove dashboard state, DNS, preview settings, or whether a
workers.devURL remains public. - A successful build is still not a complete test. A later test suite added assertions for the publication layer — canonical uniqueness, draft isolation from the sitemap, unresolvable body links, and sitemap URL counts. The handbook side has no equivalent coverage yet: required routes, language clusters, and real 404 statuses are still verified by hand.
What I would do first next time
I would start with a route sheet: current host, target path, generating source, required redirect, and whether each fact lives in Git or provider configuration. I would build and test the replacement artifact while the old deployment still served traffic, adding required-route and internal-link checks with the root build rather than as later hardening.
Before cutover I would write down the expected status and final URL for .html links, language roots, and legacy hosts. I would also keep source consolidation, deployment replacement, and language expansion in separate changes. That commit order made this migration readable, and it is the part worth repeating.
The durable result is narrower than a hosting victory lap: one build owns the main site’s static output, and one Workers Static Assets project deploys it.