It was supposed to be one link
The original task was tiny: put one external-HDD affiliate link on a site so an affiliate platform could review the implementation.
The page needed a useful article, a clear affiliate disclosure before the commercial link, and a working destination. The link was created. The article was committed to GitHub.
Then the real problem appeared.
Code existing on GitHub does not mean the page is live on the web.
The usual GitHub Actions path was unavailable. A second idea was to intercept only that URL with a Cloudflare Worker, but that route was also unavailable under the current operating constraints.
One affiliate link had somehow turned into a meeting about CI, Workers, Pages, Git integration, and Direct Upload.
That is how you accidentally begin construction on Affiliate Sagrada Família, Building No. 2.
The situation becomes much simpler once the deployment mechanisms are separated.
1. Why did the affiliate link have to be live first?
Sovrn Commerce tells content and blog publishers to implement Commerce links and generate clicks before the campaign is reviewed for approval.[3]
So the sequence is not simply “get approved, then add links.” The reviewer needs to be able to see a real implementation.
Sovrn also explains that pages containing affiliate links should clearly disclose the material relationship, and that disclosures should be visible before the affiliate promotion or link.[4]
For a basic review page, the practical requirements are modest:
- a real article exists on the submitted site;
- the article contains the affiliate link;
- the disclosure appears before that link;
- the public URL is actually reachable;
- after implementation, a small number of verification clicks can be generated.
The key distinction is simple: a file in a repository is not yet a public page.
2. GitHub Actions being unavailable does not automatically mean Cloudflare Pages is unavailable
GitHub Actions is GitHub's CI/CD system. It can build, test, and deploy a project.
Cloudflare Pages also has its own Git integration. A Pages project can connect directly to GitHub or GitLab, and Cloudflare can automatically build and deploy when changes are pushed to the connected repository.[1]
That path looks like this:
push to GitHub → Cloudflare Pages detects the commit → Cloudflare builds → Cloudflare deploys
No GitHub Actions workflow is required for that chain.
This distinction matters because “GitHub Actions is down for us” is not the same statement as “GitHub can no longer publish to Cloudflare.”
Think of GitHub Actions as an internal conveyor. Cloudflare Git integration is more like a carrier that comes to the warehouse and picks up the shipment itself.
The conveyor can be stopped while the pickup service still works.
3. First determine what kind of Pages project you already have
Cloudflare Pages becomes confusing when the project type is left ambiguous.
There are two main deployment models:
| Model | Trigger | Build/deployment location | Best fit |
|---|---|---|---|
| Git integration | push to GitHub/GitLab | Cloudflare | repository is the source of truth and deployments should be automatic |
| Direct Upload | prebuilt site output | Wrangler or dashboard | assets are built locally or in another CI system and uploaded directly |
Cloudflare documents an important limitation: a project created with Git integration cannot simply be converted into a normal Direct Upload project later. Git-integrated projects can still be manually deployed with Wrangler, but dashboard drag-and-drop is not available for those existing Git-integrated projects.[1][2]
The reverse constraint also matters. A Direct Upload project cannot later gain Git integration in place; moving to automatic Git deployment requires a new Pages project.[2]
So the first question should not be “Which deployment trick should I try?”
It should be: “Is the existing Pages project Git-integrated or Direct Upload?”
Answer that and half the maze disappears.
4. If it is Git-integrated, you do not need to resurrect GitHub Actions
When the repository is already correctly connected to Cloudflare Pages, the shortest route is neither a Worker nor a replacement CI service.
Check the Pages project itself:
- the correct GitHub repository is connected;
- the production branch is the branch you actually publish;
- automatic builds for that branch are not disabled;
- the build command and output directory match the current project;
- a new deployment appears in the Pages Deployments screen after a push;
- the updated page appears on the
pages.devdeployment; - the custom domain serves the same updated page.
Cloudflare's Git integration is designed to build and deploy from commits on the connected repository.[1]
If that path is alive, a temporary GitHub Actions restriction does not require a new deployment architecture.
Before constructing another emergency tunnel, check whether the main door is already open.
5. If it is Direct Upload, deploy the build output, not one handmade page
Direct Upload takes prebuilt assets and publishes them to Pages. Cloudflare supports uploading those assets through Wrangler or dashboard drag-and-drop for Direct Upload projects.[2]
A tempting shortcut is: “I only changed one article, so why not upload one HTML file?”
That is usually the wrong mental model for a generated static site.
The deployment unit is the built site output, not the one source file that changed. A build may also regenerate routing, CSS, JavaScript, search indexes, assets, metadata, and other pages.
A safer flow is:
get latest source → run the project's build command → inspect the output directory → deploy the complete output → verify the live URL
For a Node-based static project, the build might be something like pnpm build, producing a directory such as dist.
The goal is to avoid creating a production site that has become a mysterious manual fork of the repository.
6. If Workers are not available, remove them from the design
Routing a single emergency URL through a Worker can be technically valid.
But if Workers are unavailable under the environment's current constraints, building the rescue plan around them only increases complexity.
The decision can be reduced to:
- GitHub Actions unavailable;
- Worker path unavailable;
- therefore use either the existing Pages Git integration or the project's valid Direct Upload path.
Ten emergency exits are not necessarily safer than one known working door.
Do not build an entire second deployment system just to publish one affiliate link.
7. “Published” must be proven on the real page, not by a commit SHA
A common operations mistake is calling an intermediate step “done.”
Writing code, committing it, passing a build, and creating a deployment are all useful milestones. None of them are the final reader experience.
For an affiliate-review page, the final verification should include:
- the public URL opens in a clean browser session;
- the newest article body is visible;
- the affiliate disclosure appears before the link;
- the product link reaches the expected destination;
- the page works on mobile;
- if needed, a few verification clicks are generated;
- the affiliate dashboard reflects traffic or moves into review.
Sovrn describes the content/blog onboarding flow as implementation, click generation, then approval review.[3]
So “the code is in GitHub” is not the review starting line. The review starting line is a live implementation the reviewer can inspect.
8. At scale, do not bake affiliate URLs into the editorial body
One manual link is fine.
Hundreds or thousands of articles are different. If every article requires a human to decide whether to monetize it, where the block goes, which product to use, and which market to target, the content factory grows a second factory beside it.
A better long-term design is to separate editorial content from commercial metadata.
For example:
article_id: example-123
affiliate: true
placement: after_solution
max_products: 3
market_mode: auto
product_theme: external-storage
The publication flow can then become:
article → monetization gate → product candidates → affiliate-link creation → renderer insertion → performance measurement
The article stays a durable asset. Product URLs, stock, merchants, and country routing remain replaceable components.
An affiliate system should behave like commercial plumbing attached to the article, not like the article's concrete foundation.
9. Conclusion: when CI is unavailable, identify the real Cloudflare entrance before building another castle
The story started with one HDD affiliate link.
The link existed. The disclosure existed. The source was committed.
Then the normal CI path was unavailable, and the Worker detour was unavailable too.
At that point, adding yet another mechanism would have changed the project from “publish one link” into “build another deployment platform.”
The useful decision tree is much smaller:
- if the existing Pages project uses Git integration, use Cloudflare's native Git build path;
- if it is Direct Upload, build the complete site output and deploy it through the supported Direct Upload path;
- if Workers are unavailable, delete them from the decision tree;
- never call a Git commit a production deployment;
- verify the disclosure, link, rendering, and click behavior on the actual public URL.
The most dangerous architecture is not one with too few options.
It is one that keeps unavailable options on the diagram forever.
For one small affiliate link, the answer was unexpectedly ordinary:
first find out how the existing Cloudflare Pages project is actually deployed.
