The website preview.soubiran.dev is dedicated to my sponsors. I use it to share my upcoming writings before they are published publicly on my main website, soubiran.dev, as it’s one of the perks of sponsoring me. I also use it to centralize everything related to my GitHub sponsorships, such as announcements, exclusive articles, and more.
As the website replicates features from soubiran.dev, sponsors will be able to comment on and react to articles. These interactions will become available publicly once the article is published on the main website. This is possible thanks to the unique identifier contained in the frontmatter of each article.
Before developing this website, I used a script that copied content from pull requests in the soubiran.dev repository to discussions in the Barbapapazes-Sponsors GitHub organization. Despite being automated, this process wasn’t optimal; the content was simply placed in a code block, making it hard to read and navigate, and images were not rendered.

To provide a better experience, I wanted a dedicated website similar to soubiran.dev in terms of both design and features. The only difference is that it is only accessible to my sponsors. To do this, I’ve extracted the core of soubiran.dev into two dedicated packages, the UI and the Vite configuration, making it straightforward to build a clone.
However, soubiran.dev is a statically generated website (SSG), which means it’s not possible to protect it with traditional server-side authentication.
However, Cloudflare Workers have a feature that allows running a Worker before serving static assets using the run_worker_first option. This means I can intercept requests and perform authentication checks before any content is delivered. Using Cloudflare as my infrastructure provider, this approach makes sense. So I decided to implement authentication using a Cloudflare Worker.
The authentication layer is managed using Better Auth, using a cookie-based session. The authentication flow is as follows:
All this logic is contained within a tiny Worker script:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url)
if (authRoutes(url.pathname)) {
return auth.handler(request)
}
const session = await auth.api.getSession({
headers: request.headers,
})
if (isAnonymous(session)) {
return redirectToGitHub(request)
}
if (!hasAccess(session)) {
return tryGiveAccess(request)
}
return env.ASSETS.fetch(request)
},
}Within the “try to give access” function, a circuit breaker is implemented to automatically stop checking for sponsorship if the GitHub API is down or rate-limited, ensuring the website remains resilient.
Both the Worker and the Vite code are contained in the same repository using a pnpm monorepo. The Vite build output is used as the static assets for the Worker, configured via wrangler.jsonc.
{
"name": "preview-soubiran-dev",
"main": "src/worker.ts",
"assets": {
"directory": "../dist", // Vite build output
"binding": "ASSETS",
"run_worker_first": true
}
}The build and deployment are fully automated using Cloudflare Build. First, the Vite project is built using vite build, and then the Worker is built using wrangler deploy. Finally, the Worker is deployed to the Cloudflare Workers platform, and thanks to the configuration, the static assets are deployed alongside it.
Now, every request to preview.soubiran.dev goes through the Worker, which handles identity management and serves the static assets.
I thought a lot about how to implement custom authentication for external users in front of a static website.
Note
The “external” part is important as I can’t rely on Cloudflare Access for non-team members.
The first idea was to use a backend framework like Laravel to implement the authentication. I could have built the static website within its static assets folder. This was feasible, but maintaining and deploying a full backend just for authentication wasn’t something I wanted to do for infra.soubiran.dev.
Another solution was also to use Laravel, but instead of generating static assets, I could have built a Markdown pipeline to render articles on-demand after an authentication check. This solution required more work, as I would have had to implement Markdown rendering within Laravel. This isn’t something I want to do, as I already have a pipeline for soubiran.dev and I want to reuse it as much as possible.
Cloudflare Workers naturally appeared as the best solution to my problem, as everything is managed by Cloudflare, from deployment to production. The only thing I have to do is write the Worker and static website code, and Cloudflare Build takes care of the rest.